/*
* TCP Reno congestion control
* This is special case used for fallback as well.
*/
/* This is Jacobson's slow start and congestion avoidance.
* SIGCOMM '88, p. 328.
*/
void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
{
struct tcp_sock *tp = tcp_sk(sk); // 获取tcp_sock
// 函数返回1说明拥塞窗口被限制,我们需要增加拥塞窗口,否则的话,就不需要增加拥塞窗口。
if (!tcp_is_cwnd_limited(sk, in_flight)) // 是否已经达到拥塞窗口的限制值(1)
return;
/* In "safe" area, increase. */
if (tp->snd_cwnd <= tp->snd_ssthresh) // 如果发送窗口大小还 比 慢开始门限小,那么还是慢开始处理
tcp_slow_start(tp); // 下面进入慢开始处理 (2)
/* In dangerous area, increase slowly. */
else if (sysctl_tcp_abc) { // 否则进入拥塞避免阶段!!每个RTT时间就加1
/* RFC3465: Appropriate Byte Count
* increase once for each full cwnd acked // 基本思想就是:经过一个RTT时间就将snd_cwnd增加一个单位!
*/ // 一个RTT时间可以认为是当前拥塞窗口发送出去的数据的所有ACK都被接收到
if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) { // 当前的拥塞窗口的所有段都被ack了,窗口才被允许增加。
tp->bytes_acked -= tp->snd_cwnd*tp->mss_cache; // ACK处理过的及删除去了
if (tp->snd_cwnd < tp->snd_cwnd_clamp) // 不允许发送窗口大小超过snd_cwnd_clamp值
tp->snd_cwnd++;
}
} else { // 每接收到一个ACK,窗口增大(1/snd_cwnd),使用cnt计数
/* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd */
if (tp->snd_cwnd_cnt >= tp->snd_cwnd) { // 线性增长计数器 >= 阈值
if (tp->snd_cwnd < tp->snd_cwnd_clamp) // 如果窗口还没有达到阈值
tp->snd_cwnd++; // 那么++增大窗口
tp->snd_cwnd_cnt = 0;
} else
tp->snd_cwnd_cnt++; // 否则仅仅是增大线性递增计数器
}
}
参考
http://blog.csdn.net/shanshanpt/article/details/22201847