xref: /linux/net/ipv4/tcp_scalable.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20e57976bSJohn Heffner /* Tom Kelly's Scalable TCP
30e57976bSJohn Heffner  *
4a52b8bd3SJoe Perches  * See http://www.deneholme.net/tom/scalable/
50e57976bSJohn Heffner  *
60e57976bSJohn Heffner  * John Heffner <jheffner@sc.edu>
70e57976bSJohn Heffner  */
80e57976bSJohn Heffner 
90e57976bSJohn Heffner #include <linux/module.h>
100e57976bSJohn Heffner #include <net/tcp.h>
110e57976bSJohn Heffner 
120e57976bSJohn Heffner /* These factors derived from the recommended values in the aer:
132bdcc73cSRandy Dunlap  * .01 and 7/8.
140e57976bSJohn Heffner  */
155415e3c3SPengcheng Yang #define TCP_SCALABLE_AI_CNT	100U
160e57976bSJohn Heffner #define TCP_SCALABLE_MD_SCALE	3
170e57976bSJohn Heffner 
tcp_scalable_cong_avoid(struct sock * sk,u32 ack,u32 acked)1824901551SEric Dumazet static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 acked)
190e57976bSJohn Heffner {
206687e988SArnaldo Carvalho de Melo 	struct tcp_sock *tp = tcp_sk(sk);
21f4805edeSStephen Hemminger 
2224901551SEric Dumazet 	if (!tcp_is_cwnd_limited(sk))
230e57976bSJohn Heffner 		return;
240e57976bSJohn Heffner 
255415e3c3SPengcheng Yang 	if (tcp_in_slow_start(tp)) {
265415e3c3SPengcheng Yang 		acked = tcp_slow_start(tp, acked);
275415e3c3SPengcheng Yang 		if (!acked)
285415e3c3SPengcheng Yang 			return;
295415e3c3SPengcheng Yang 	}
30*40570375SEric Dumazet 	tcp_cong_avoid_ai(tp, min(tcp_snd_cwnd(tp), TCP_SCALABLE_AI_CNT),
315415e3c3SPengcheng Yang 			  acked);
320e57976bSJohn Heffner }
330e57976bSJohn Heffner 
tcp_scalable_ssthresh(struct sock * sk)346687e988SArnaldo Carvalho de Melo static u32 tcp_scalable_ssthresh(struct sock *sk)
350e57976bSJohn Heffner {
366687e988SArnaldo Carvalho de Melo 	const struct tcp_sock *tp = tcp_sk(sk);
37688d1945Sstephen hemminger 
38*40570375SEric Dumazet 	return max(tcp_snd_cwnd(tp) - (tcp_snd_cwnd(tp)>>TCP_SCALABLE_MD_SCALE), 2U);
390e57976bSJohn Heffner }
400e57976bSJohn Heffner 
41a252bebeSStephen Hemminger static struct tcp_congestion_ops tcp_scalable __read_mostly = {
420e57976bSJohn Heffner 	.ssthresh	= tcp_scalable_ssthresh,
43f1722a1bSYuchung Cheng 	.undo_cwnd	= tcp_reno_undo_cwnd,
440e57976bSJohn Heffner 	.cong_avoid	= tcp_scalable_cong_avoid,
450e57976bSJohn Heffner 
460e57976bSJohn Heffner 	.owner		= THIS_MODULE,
470e57976bSJohn Heffner 	.name		= "scalable",
480e57976bSJohn Heffner };
490e57976bSJohn Heffner 
tcp_scalable_register(void)500e57976bSJohn Heffner static int __init tcp_scalable_register(void)
510e57976bSJohn Heffner {
520e57976bSJohn Heffner 	return tcp_register_congestion_control(&tcp_scalable);
530e57976bSJohn Heffner }
540e57976bSJohn Heffner 
tcp_scalable_unregister(void)550e57976bSJohn Heffner static void __exit tcp_scalable_unregister(void)
560e57976bSJohn Heffner {
570e57976bSJohn Heffner 	tcp_unregister_congestion_control(&tcp_scalable);
580e57976bSJohn Heffner }
590e57976bSJohn Heffner 
600e57976bSJohn Heffner module_init(tcp_scalable_register);
610e57976bSJohn Heffner module_exit(tcp_scalable_unregister);
620e57976bSJohn Heffner 
630e57976bSJohn Heffner MODULE_AUTHOR("John Heffner");
640e57976bSJohn Heffner MODULE_LICENSE("GPL");
650e57976bSJohn Heffner MODULE_DESCRIPTION("Scalable TCP");
66