xref: /linux/net/ipv4/tcp_scalable.c (revision a252bebe22155313ccdadc20b79f67a239dc9ecb)
10e57976bSJohn Heffner /* Tom Kelly's Scalable TCP
20e57976bSJohn Heffner  *
3a52b8bd3SJoe Perches  * See http://www.deneholme.net/tom/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 
18c3a05c60SIlpo 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);
27758ce5c8SIlpo Järvinen 	else
28758ce5c8SIlpo Järvinen 		tcp_cong_avoid_ai(tp, min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT));
290e57976bSJohn Heffner }
300e57976bSJohn Heffner 
316687e988SArnaldo Carvalho de Melo static u32 tcp_scalable_ssthresh(struct sock *sk)
320e57976bSJohn Heffner {
336687e988SArnaldo Carvalho de Melo 	const struct tcp_sock *tp = tcp_sk(sk);
340e57976bSJohn Heffner 	return max(tp->snd_cwnd - (tp->snd_cwnd>>TCP_SCALABLE_MD_SCALE), 2U);
350e57976bSJohn Heffner }
360e57976bSJohn Heffner 
370e57976bSJohn Heffner 
38*a252bebeSStephen Hemminger static struct tcp_congestion_ops tcp_scalable __read_mostly = {
390e57976bSJohn Heffner 	.ssthresh	= tcp_scalable_ssthresh,
400e57976bSJohn Heffner 	.cong_avoid	= tcp_scalable_cong_avoid,
410e57976bSJohn Heffner 	.min_cwnd	= tcp_reno_min_cwnd,
420e57976bSJohn Heffner 
430e57976bSJohn Heffner 	.owner		= THIS_MODULE,
440e57976bSJohn Heffner 	.name		= "scalable",
450e57976bSJohn Heffner };
460e57976bSJohn Heffner 
470e57976bSJohn Heffner static int __init tcp_scalable_register(void)
480e57976bSJohn Heffner {
490e57976bSJohn Heffner 	return tcp_register_congestion_control(&tcp_scalable);
500e57976bSJohn Heffner }
510e57976bSJohn Heffner 
520e57976bSJohn Heffner static void __exit tcp_scalable_unregister(void)
530e57976bSJohn Heffner {
540e57976bSJohn Heffner 	tcp_unregister_congestion_control(&tcp_scalable);
550e57976bSJohn Heffner }
560e57976bSJohn Heffner 
570e57976bSJohn Heffner module_init(tcp_scalable_register);
580e57976bSJohn Heffner module_exit(tcp_scalable_unregister);
590e57976bSJohn Heffner 
600e57976bSJohn Heffner MODULE_AUTHOR("John Heffner");
610e57976bSJohn Heffner MODULE_LICENSE("GPL");
620e57976bSJohn Heffner MODULE_DESCRIPTION("Scalable TCP");
63