aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2007-08-02 22:47:59 -0400
committerDavid S. Miller <davem@davemloft.net>2007-08-02 22:47:59 -0400
commit49ff4bb4cd4c04acf8f9e3d3ec2148305a1db445 (patch)
tree3e443a0cf902c02d8046617c24700745a1afecd0 /net
parent2e6052941ae1f2f875d7d9092acb8836af1e0193 (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.c5
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;