diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2007-08-02 22:47:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-08-02 22:47:59 -0400 |
commit | 49ff4bb4cd4c04acf8f9e3d3ec2148305a1db445 (patch) | |
tree | 3e443a0cf902c02d8046617c24700745a1afecd0 /net | |
parent | 2e6052941ae1f2f875d7d9092acb8836af1e0193 (diff) |
[TCP]: DSACK signals data receival, be conservative
In case a DSACK is received, it's better to lower cwnd as it's
a sign of data receival.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_input.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index c3124e6de1d3..f030435e0eb4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -103,6 +103,7 @@ int sysctl_tcp_abc __read_mostly; | |||
103 | #define FLAG_SLOWPATH 0x100 /* Do not skip RFC checks for window update.*/ | 103 | #define FLAG_SLOWPATH 0x100 /* Do not skip RFC checks for window update.*/ |
104 | #define FLAG_ONLY_ORIG_SACKED 0x200 /* SACKs only non-rexmit sent before RTO */ | 104 | #define FLAG_ONLY_ORIG_SACKED 0x200 /* SACKs only non-rexmit sent before RTO */ |
105 | #define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */ | 105 | #define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */ |
106 | #define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained DSACK info */ | ||
106 | 107 | ||
107 | #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) | 108 | #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) |
108 | #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) | 109 | #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) |
@@ -966,12 +967,14 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
966 | 967 | ||
967 | /* Check for D-SACK. */ | 968 | /* Check for D-SACK. */ |
968 | if (before(ntohl(sp[0].start_seq), TCP_SKB_CB(ack_skb)->ack_seq)) { | 969 | if (before(ntohl(sp[0].start_seq), TCP_SKB_CB(ack_skb)->ack_seq)) { |
970 | flag |= FLAG_DSACKING_ACK; | ||
969 | found_dup_sack = 1; | 971 | found_dup_sack = 1; |
970 | tp->rx_opt.sack_ok |= 4; | 972 | tp->rx_opt.sack_ok |= 4; |
971 | NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV); | 973 | NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV); |
972 | } else if (num_sacks > 1 && | 974 | } else if (num_sacks > 1 && |
973 | !after(ntohl(sp[0].end_seq), ntohl(sp[1].end_seq)) && | 975 | !after(ntohl(sp[0].end_seq), ntohl(sp[1].end_seq)) && |
974 | !before(ntohl(sp[0].start_seq), ntohl(sp[1].start_seq))) { | 976 | !before(ntohl(sp[0].start_seq), ntohl(sp[1].start_seq))) { |
977 | flag |= FLAG_DSACKING_ACK; | ||
975 | found_dup_sack = 1; | 978 | found_dup_sack = 1; |
976 | tp->rx_opt.sack_ok |= 4; | 979 | tp->rx_opt.sack_ok |= 4; |
977 | NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV); | 980 | NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV); |
@@ -1858,7 +1861,7 @@ static void tcp_cwnd_down(struct sock *sk, int flag) | |||
1858 | struct tcp_sock *tp = tcp_sk(sk); | 1861 | struct tcp_sock *tp = tcp_sk(sk); |
1859 | int decr = tp->snd_cwnd_cnt + 1; | 1862 | int decr = tp->snd_cwnd_cnt + 1; |
1860 | 1863 | ||
1861 | if ((flag&FLAG_ANY_PROGRESS) || | 1864 | if ((flag&(FLAG_ANY_PROGRESS|FLAG_DSACKING_ACK)) || |
1862 | (IsReno(tp) && !(flag&FLAG_NOT_DUP))) { | 1865 | (IsReno(tp) && !(flag&FLAG_NOT_DUP))) { |
1863 | tp->snd_cwnd_cnt = decr&1; | 1866 | tp->snd_cwnd_cnt = decr&1; |
1864 | decr >>= 1; | 1867 | decr >>= 1; |