diff options
author | Xiaoliang (David) Wei <davidwei79@gmail.com> | 2006-07-11 13:03:28 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-07-12 13:58:50 -0700 |
commit | 6150c22e2ac3f7dbe73e7ae7817785070d0cff1f (patch) | |
tree | 2506ea47e5ae101ab6f0df694480b1df46267b18 /net/ipv4/tcp_highspeed.c | |
parent | 781b456a980ec987a4be248f236c59658f651240 (diff) | |
download | linux-stable-6150c22e2ac3f7dbe73e7ae7817785070d0cff1f.tar.gz linux-stable-6150c22e2ac3f7dbe73e7ae7817785070d0cff1f.tar.bz2 linux-stable-6150c22e2ac3f7dbe73e7ae7817785070d0cff1f.zip |
[TCP] tcp_highspeed: Fix AI updates.
I think there is still a problem with the AIMD parameter update in
HighSpeed TCP code.
Line 125~138 of the code (net/ipv4/tcp_highspeed.c):
/* Update AIMD parameters */
if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) {
while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
ca->ai < HSTCP_AIMD_MAX - 1)
ca->ai++;
} else if (tp->snd_cwnd < hstcp_aimd_vals[ca->ai].cwnd) {
while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
ca->ai > 0)
ca->ai--;
In fact, the second part (decreasing ca->ai) never decreases since the
while loop's inequality is in the reverse direction. This leads to
unfairness with multiple flows (once a flow happens to enjoy a higher
ca->ai, it keeps enjoying that even its cwnd decreases)
Here is a tentative fix (I also added a comment, trying to keep the
change clear):
Acked-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_highspeed.c')
-rw-r--r-- | net/ipv4/tcp_highspeed.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c index aaa1538c0692..fa3e1aad660c 100644 --- a/net/ipv4/tcp_highspeed.c +++ b/net/ipv4/tcp_highspeed.c @@ -139,14 +139,19 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt, tp->snd_cwnd++; } } else { - /* Update AIMD parameters */ + /* Update AIMD parameters. + * + * We want to guarantee that: + * hstcp_aimd_vals[ca->ai-1].cwnd < + * snd_cwnd <= + * hstcp_aimd_vals[ca->ai].cwnd + */ if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) { while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd && ca->ai < HSTCP_AIMD_MAX - 1) ca->ai++; - } else if (tp->snd_cwnd < hstcp_aimd_vals[ca->ai].cwnd) { - while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd && - ca->ai > 0) + } else if (ca->ai && tp->snd_cwnd <= hstcp_aimd_vals[ca->ai-1].cwnd) { + while (ca->ai && tp->snd_cwnd <= hstcp_aimd_vals[ca->ai-1].cwnd) ca->ai--; } |