#include #include int sysctl_tcp_max_ssthresh = 0; /* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd (or alternative w) */ void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w) { if (tp->snd_cwnd_cnt >= w) { if (tp->snd_cwnd < tp->snd_cwnd_clamp) tp->snd_cwnd++; tp->snd_cwnd_cnt = 0; } else { tp->snd_cwnd_cnt++; } } static void exp_slow_start(struct tcp_sock *tp) { /* Handle cwnd manipulation for slow start here */ int cnt; /* increase in packets */ unsigned int delta = 0; u32 snd_cwnd = tp->snd_cwnd; if (unlikely(!snd_cwnd)) { printk("snd_cwnd is nul, please report this bug.\n"); snd_cwnd = 1U; } if (sysctl_tcp_max_ssthresh > 0 && tp->snd_cwnd > sysctl_tcp_max_ssthresh) cnt = sysctl_tcp_max_ssthresh >> 1; /* limited slow start */ else cnt = snd_cwnd * 2; /* changed by Shufeng - exponential factor 3 increase */ tp->snd_cwnd_cnt += cnt; while (tp->snd_cwnd_cnt >= snd_cwnd) { tp->snd_cwnd_cnt -= snd_cwnd; delta++; } tp->snd_cwnd = min(snd_cwnd + delta, tp->snd_cwnd_clamp); } static void exp_cong_avoid(struct sock *sk, u32 adk, u32 in_flight) { /* Handle cwnd manipulation for congestion avoidance here */ struct tcp_sock *tp = tcp_sk(sk); if (!tcp_is_cwnd_limited(sk, in_flight)) return; /* In "safe" area, increase. */ if (tp->snd_cwnd <= tp->snd_ssthresh) exp_slow_start(tp); /* In dangerous area, increase slowly. */ else tcp_cong_avoid_ai(tp, tp->snd_cwnd); } static u32 exp_ssthresh(struct sock *sk) { /* Compute the appropriate value of ssthresh here */ const struct tcp_sock *tp = tcp_sk(sk); return max(tp->snd_cwnd*3/4, 2U); //changed by Shufeng } //See http://lwn.net/Articles/128681/ for more information /* * The start() method initializes the algorithm when a new batch of data * is being transmitted; this can happen for new sockets, or when one * has been idle for a while. * * The ssthresh() method calculates the "slow start threshold"; when the * congestion window is below that threshold, the connection is in slow * start mode rather than full congestion avoidance mode. This method is * called when congestion occurs. * * The actual initial window may be set by min_cwnd() to be less than * the threshold value as a starting point for the slow start algorithm. * * When an acknowledgment arrives from the remote end, the cong_avoid() * method is invoked; it may respond to successful packet delivery by * enlarging the congestion window. * * rtt_sample() tells the algorithm about a measured round-trip time - * the time taken between sending a packet and receiving the * corresponding acknowledgment. * * set_state() indicates that the TCP state of the socket has changed. * * Various events of interest can be communicated to the algorithm via * cwnd_event(). * * Sometimes, transient situations can cause the congestion window to be * reduced; the undo_cwnd() method can be called when such a situation * is detected to restore a larger window. * * The get_info() method can be used to make congestion avoidance * information available to user space. */ static struct tcp_congestion_ops tcp_exp __read_mostly = { .init = NULL, .ssthresh = exp_ssthresh, .cong_avoid = exp_cong_avoid, .min_cwnd = tcp_reno_min_cwnd, .owner = THIS_MODULE, .name = "exp" }; static int __init exp_register(void) { return tcp_register_congestion_control(&tcp_exp); } static void __exit exp_unregister(void) { tcp_unregister_congestion_control(&tcp_exp); } module_init(exp_register); module_exit(exp_unregister); MODULE_AUTHOR("Shufeng Huang"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Experimental TCP");