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