^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Sally Floyd's High Speed TCP (RFC 3649) congestion control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * See https://www.icir.org/floyd/hstcp.html
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * John Heffner <jheffner@psc.edu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <net/tcp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /* From AIMD tables from RFC 3649 appendix B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * with fixed-point MD scaled <<8.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static const struct hstcp_aimd_val {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) unsigned int cwnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned int md;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) } hstcp_aimd_vals[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) { 38, 128, /* 0.50 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) { 118, 112, /* 0.44 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) { 221, 104, /* 0.41 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) { 347, 98, /* 0.38 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) { 495, 93, /* 0.37 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) { 663, 89, /* 0.35 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) { 851, 86, /* 0.34 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) { 1058, 83, /* 0.33 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) { 1284, 81, /* 0.32 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) { 1529, 78, /* 0.31 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) { 1793, 76, /* 0.30 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) { 2076, 74, /* 0.29 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) { 2378, 72, /* 0.28 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) { 2699, 71, /* 0.28 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) { 3039, 69, /* 0.27 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) { 3399, 68, /* 0.27 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) { 3778, 66, /* 0.26 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) { 4177, 65, /* 0.26 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) { 4596, 64, /* 0.25 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) { 5036, 62, /* 0.25 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) { 5497, 61, /* 0.24 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) { 5979, 60, /* 0.24 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) { 6483, 59, /* 0.23 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) { 7009, 58, /* 0.23 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) { 7558, 57, /* 0.22 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { 8130, 56, /* 0.22 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) { 8726, 55, /* 0.22 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) { 9346, 54, /* 0.21 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) { 9991, 53, /* 0.21 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) { 10661, 52, /* 0.21 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { 11358, 52, /* 0.20 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { 12082, 51, /* 0.20 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { 12834, 50, /* 0.20 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { 13614, 49, /* 0.19 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { 14424, 48, /* 0.19 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { 15265, 48, /* 0.19 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { 16137, 47, /* 0.19 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { 17042, 46, /* 0.18 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { 17981, 45, /* 0.18 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { 18955, 45, /* 0.18 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { 19965, 44, /* 0.17 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { 21013, 43, /* 0.17 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { 22101, 43, /* 0.17 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { 23230, 42, /* 0.17 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { 24402, 41, /* 0.16 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { 25618, 41, /* 0.16 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { 26881, 40, /* 0.16 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) { 28193, 39, /* 0.16 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { 29557, 39, /* 0.15 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { 30975, 38, /* 0.15 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { 32450, 38, /* 0.15 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { 33986, 37, /* 0.15 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) { 35586, 36, /* 0.14 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) { 37253, 36, /* 0.14 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { 38992, 35, /* 0.14 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { 40808, 35, /* 0.14 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { 42707, 34, /* 0.13 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { 44694, 33, /* 0.13 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { 46776, 33, /* 0.13 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { 48961, 32, /* 0.13 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { 51258, 32, /* 0.13 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { 53677, 31, /* 0.12 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) { 56230, 30, /* 0.12 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { 58932, 30, /* 0.12 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { 61799, 29, /* 0.12 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) { 64851, 28, /* 0.11 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) { 68113, 28, /* 0.11 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) { 71617, 27, /* 0.11 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { 75401, 26, /* 0.10 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { 79517, 26, /* 0.10 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) { 84035, 25, /* 0.10 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) { 89053, 24, /* 0.10 */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define HSTCP_AIMD_MAX ARRAY_SIZE(hstcp_aimd_vals)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct hstcp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u32 ai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static void hstcp_init(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct tcp_sock *tp = tcp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct hstcp *ca = inet_csk_ca(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ca->ai = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* Ensure the MD arithmetic works. This is somewhat pedantic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * since I don't think we will see a cwnd this large. :) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) tp->snd_cwnd_clamp = min_t(u32, tp->snd_cwnd_clamp, 0xffffffff/128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static void hstcp_cong_avoid(struct sock *sk, u32 ack, u32 acked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct tcp_sock *tp = tcp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct hstcp *ca = inet_csk_ca(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (!tcp_is_cwnd_limited(sk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (tcp_in_slow_start(tp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) tcp_slow_start(tp, acked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* Update AIMD parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * We want to guarantee that:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * hstcp_aimd_vals[ca->ai-1].cwnd <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * snd_cwnd <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * hstcp_aimd_vals[ca->ai].cwnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ca->ai < HSTCP_AIMD_MAX - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ca->ai++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) } else if (ca->ai && tp->snd_cwnd <= hstcp_aimd_vals[ca->ai-1].cwnd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) while (ca->ai && tp->snd_cwnd <= hstcp_aimd_vals[ca->ai-1].cwnd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ca->ai--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* Do additive increase */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* cwnd = cwnd + a(w) / cwnd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) tp->snd_cwnd_cnt += ca->ai + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) tp->snd_cwnd_cnt -= tp->snd_cwnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) tp->snd_cwnd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static u32 hstcp_ssthresh(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) const struct tcp_sock *tp = tcp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct hstcp *ca = inet_csk_ca(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* Do multiplicative decrease */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return max(tp->snd_cwnd - ((tp->snd_cwnd * hstcp_aimd_vals[ca->ai].md) >> 8), 2U);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static struct tcp_congestion_ops tcp_highspeed __read_mostly = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .init = hstcp_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .ssthresh = hstcp_ssthresh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .undo_cwnd = tcp_reno_undo_cwnd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .cong_avoid = hstcp_cong_avoid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .name = "highspeed"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static int __init hstcp_register(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) BUILD_BUG_ON(sizeof(struct hstcp) > ICSK_CA_PRIV_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return tcp_register_congestion_control(&tcp_highspeed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static void __exit hstcp_unregister(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) tcp_unregister_congestion_control(&tcp_highspeed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) module_init(hstcp_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) module_exit(hstcp_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) MODULE_AUTHOR("John Heffner");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) MODULE_DESCRIPTION("High Speed TCP");