xref: /linux/net/ipv4/tcp_scalable.c (revision c3a05c6050a339c92e49fae0ba77dbba0d41fd99)
10e57976bSJohn Heffner /* Tom Kelly's Scalable TCP
20e57976bSJohn Heffner  *
30e57976bSJohn Heffner  * See htt://www-lce.eng.cam.ac.uk/~ctk21/scalable/
40e57976bSJohn Heffner  *
50e57976bSJohn Heffner  * John Heffner <jheffner@sc.edu>
60e57976bSJohn Heffner  */
70e57976bSJohn Heffner 
80e57976bSJohn Heffner #include <linux/module.h>
90e57976bSJohn Heffner #include <net/tcp.h>
100e57976bSJohn Heffner 
110e57976bSJohn Heffner /* These factors derived from the recommended values in the aer:
120e57976bSJohn Heffner  * .01 and and 7/8. We use 50 instead of 100 to account for
130e57976bSJohn Heffner  * delayed ack.
140e57976bSJohn Heffner  */
150e57976bSJohn Heffner #define TCP_SCALABLE_AI_CNT	50U
160e57976bSJohn Heffner #define TCP_SCALABLE_MD_SCALE	3
170e57976bSJohn Heffner 
18*c3a05c60SIlpo Järvinen static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
190e57976bSJohn Heffner {
206687e988SArnaldo Carvalho de Melo 	struct tcp_sock *tp = tcp_sk(sk);
21f4805edeSStephen Hemminger 
22f4805edeSStephen Hemminger 	if (!tcp_is_cwnd_limited(sk, in_flight))
230e57976bSJohn Heffner 		return;
240e57976bSJohn Heffner 
257faffa1cSStephen Hemminger 	if (tp->snd_cwnd <= tp->snd_ssthresh)
267faffa1cSStephen Hemminger 		tcp_slow_start(tp);
277faffa1cSStephen Hemminger 	else {
280e57976bSJohn Heffner 		tp->snd_cwnd_cnt++;
290e57976bSJohn Heffner 		if (tp->snd_cwnd_cnt > min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)){
307faffa1cSStephen Hemminger 			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
310e57976bSJohn Heffner 				tp->snd_cwnd++;
320e57976bSJohn Heffner 			tp->snd_cwnd_cnt = 0;
330e57976bSJohn Heffner 		}
340e57976bSJohn Heffner 	}
350e57976bSJohn Heffner }
360e57976bSJohn Heffner 
376687e988SArnaldo Carvalho de Melo static u32 tcp_scalable_ssthresh(struct sock *sk)
380e57976bSJohn Heffner {
396687e988SArnaldo Carvalho de Melo 	const struct tcp_sock *tp = tcp_sk(sk);
400e57976bSJohn Heffner 	return max(tp->snd_cwnd - (tp->snd_cwnd>>TCP_SCALABLE_MD_SCALE), 2U);
410e57976bSJohn Heffner }
420e57976bSJohn Heffner 
430e57976bSJohn Heffner 
440e57976bSJohn Heffner static struct tcp_congestion_ops tcp_scalable = {
450e57976bSJohn Heffner 	.ssthresh	= tcp_scalable_ssthresh,
460e57976bSJohn Heffner 	.cong_avoid	= tcp_scalable_cong_avoid,
470e57976bSJohn Heffner 	.min_cwnd	= tcp_reno_min_cwnd,
480e57976bSJohn Heffner 
490e57976bSJohn Heffner 	.owner		= THIS_MODULE,
500e57976bSJohn Heffner 	.name		= "scalable",
510e57976bSJohn Heffner };
520e57976bSJohn Heffner 
530e57976bSJohn Heffner static int __init tcp_scalable_register(void)
540e57976bSJohn Heffner {
550e57976bSJohn Heffner 	return tcp_register_congestion_control(&tcp_scalable);
560e57976bSJohn Heffner }
570e57976bSJohn Heffner 
580e57976bSJohn Heffner static void __exit tcp_scalable_unregister(void)
590e57976bSJohn Heffner {
600e57976bSJohn Heffner 	tcp_unregister_congestion_control(&tcp_scalable);
610e57976bSJohn Heffner }
620e57976bSJohn Heffner 
630e57976bSJohn Heffner module_init(tcp_scalable_register);
640e57976bSJohn Heffner module_exit(tcp_scalable_unregister);
650e57976bSJohn Heffner 
660e57976bSJohn Heffner MODULE_AUTHOR("John Heffner");
670e57976bSJohn Heffner MODULE_LICENSE("GPL");
680e57976bSJohn Heffner MODULE_DESCRIPTION("Scalable TCP");
69