2005-06-23 23:29:07 +04:00
/* Tom Kelly's Scalable TCP
*
* See htt : //www-lce.eng.cam.ac.uk/~ctk21/scalable/
*
* John Heffner < jheffner @ sc . edu >
*/
# include <linux/module.h>
# include <net/tcp.h>
/* These factors derived from the recommended values in the aer:
* .01 and and 7 / 8. We use 50 instead of 100 to account for
* delayed ack .
*/
# define TCP_SCALABLE_AI_CNT 50U
# define TCP_SCALABLE_MD_SCALE 3
2007-12-02 01:47:59 +03:00
static void tcp_scalable_cong_avoid ( struct sock * sk , u32 ack , u32 in_flight )
2005-06-23 23:29:07 +04:00
{
2005-08-10 11:03:31 +04:00
struct tcp_sock * tp = tcp_sk ( sk ) ;
2005-11-11 03:53:30 +03:00
if ( ! tcp_is_cwnd_limited ( sk , in_flight ) )
2005-06-23 23:29:07 +04:00
return ;
2005-11-11 04:07:24 +03:00
if ( tp - > snd_cwnd < = tp - > snd_ssthresh )
tcp_slow_start ( tp ) ;
else {
2005-06-23 23:29:07 +04:00
tp - > snd_cwnd_cnt + + ;
if ( tp - > snd_cwnd_cnt > min ( tp - > snd_cwnd , TCP_SCALABLE_AI_CNT ) ) {
2005-11-11 04:07:24 +03:00
if ( tp - > snd_cwnd < tp - > snd_cwnd_clamp )
tp - > snd_cwnd + + ;
2005-06-23 23:29:07 +04:00
tp - > snd_cwnd_cnt = 0 ;
}
}
}
2005-08-10 11:03:31 +04:00
static u32 tcp_scalable_ssthresh ( struct sock * sk )
2005-06-23 23:29:07 +04:00
{
2005-08-10 11:03:31 +04:00
const struct tcp_sock * tp = tcp_sk ( sk ) ;
2005-06-23 23:29:07 +04:00
return max ( tp - > snd_cwnd - ( tp - > snd_cwnd > > TCP_SCALABLE_MD_SCALE ) , 2U ) ;
}
static struct tcp_congestion_ops tcp_scalable = {
. ssthresh = tcp_scalable_ssthresh ,
. cong_avoid = tcp_scalable_cong_avoid ,
. min_cwnd = tcp_reno_min_cwnd ,
. owner = THIS_MODULE ,
. name = " scalable " ,
} ;
static int __init tcp_scalable_register ( void )
{
return tcp_register_congestion_control ( & tcp_scalable ) ;
}
static void __exit tcp_scalable_unregister ( void )
{
tcp_unregister_congestion_control ( & tcp_scalable ) ;
}
module_init ( tcp_scalable_register ) ;
module_exit ( tcp_scalable_unregister ) ;
MODULE_AUTHOR ( " John Heffner " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " Scalable TCP " ) ;