Commit 94d3b1e5 authored by Ryousei Takano's avatar Ryousei Takano Committed by David S. Miller

[TCP]: fix D-SACK cwnd handling

In the current net-2.6 kernel, handling FLAG_DSACKING_ACK is broken.
The flag is cleared to 1 just after FLAG_DSACKING_ACK is set.

        if (found_dup_sack)
                flag |= FLAG_DSACKING_ACK;
	:
	flag = 1;

To fix it, this patch introduces a part of the tcp_sacktag_state patch:
	http://marc.info/?l=linux-netdev&m=119210560431519&w=2Signed-off-by: default avatarRyousei Takano <takano-ryousei@aist.go.jp>
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 43cc7380
...@@ -1248,6 +1248,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ ...@@ -1248,6 +1248,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
int cached_fack_count; int cached_fack_count;
int i; int i;
int first_sack_index; int first_sack_index;
int force_one_sack;
if (!tp->sacked_out) { if (!tp->sacked_out) {
if (WARN_ON(tp->fackets_out)) if (WARN_ON(tp->fackets_out))
...@@ -1272,18 +1273,18 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ ...@@ -1272,18 +1273,18 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
* if the only SACK change is the increase of the end_seq of * if the only SACK change is the increase of the end_seq of
* the first block then only apply that SACK block * the first block then only apply that SACK block
* and use retrans queue hinting otherwise slowpath */ * and use retrans queue hinting otherwise slowpath */
flag = 1; force_one_sack = 1;
for (i = 0; i < num_sacks; i++) { for (i = 0; i < num_sacks; i++) {
__be32 start_seq = sp[i].start_seq; __be32 start_seq = sp[i].start_seq;
__be32 end_seq = sp[i].end_seq; __be32 end_seq = sp[i].end_seq;
if (i == 0) { if (i == 0) {
if (tp->recv_sack_cache[i].start_seq != start_seq) if (tp->recv_sack_cache[i].start_seq != start_seq)
flag = 0; force_one_sack = 0;
} else { } else {
if ((tp->recv_sack_cache[i].start_seq != start_seq) || if ((tp->recv_sack_cache[i].start_seq != start_seq) ||
(tp->recv_sack_cache[i].end_seq != end_seq)) (tp->recv_sack_cache[i].end_seq != end_seq))
flag = 0; force_one_sack = 0;
} }
tp->recv_sack_cache[i].start_seq = start_seq; tp->recv_sack_cache[i].start_seq = start_seq;
tp->recv_sack_cache[i].end_seq = end_seq; tp->recv_sack_cache[i].end_seq = end_seq;
...@@ -1295,7 +1296,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ ...@@ -1295,7 +1296,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
} }
first_sack_index = 0; first_sack_index = 0;
if (flag) if (force_one_sack)
num_sacks = 1; num_sacks = 1;
else { else {
int j; int j;
...@@ -1321,9 +1322,6 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ ...@@ -1321,9 +1322,6 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
} }
} }
/* clear flag as used for different purpose in following code */
flag = 0;
/* Use SACK fastpath hint if valid */ /* Use SACK fastpath hint if valid */
cached_skb = tp->fastpath_skb_hint; cached_skb = tp->fastpath_skb_hint;
cached_fack_count = tp->fastpath_cnt_hint; cached_fack_count = tp->fastpath_cnt_hint;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment