aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_output.c
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2008-09-21 00:26:22 -0400
committerDavid S. Miller <davem@davemloft.net>2008-09-21 00:26:22 -0400
commit618d9f25548ba6fc3a9cd2ce5cd56f4f015b0635 (patch)
treef04a91ec4aac1fc4bcb0b8204a8ff64c3844e6de /net/ipv4/tcp_output.c
parent90638a04ad8484b6b6c567656fb3f6d0689e23da (diff)
tcp: back retransmit_high when it over-estimated
If lost skb is sacked, we might have nothing to retransmit as high as the retransmit_high is pointing to, so place it lower to avoid unnecessary walking. This is mainly for the case where high L'ed skbs gets sacked. Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r--net/ipv4/tcp_output.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 239cea7b6c0e..8f9793a37b61 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2035,16 +2035,22 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
2035 struct tcp_sock *tp = tcp_sk(sk); 2035 struct tcp_sock *tp = tcp_sk(sk);
2036 struct sk_buff *skb; 2036 struct sk_buff *skb;
2037 struct sk_buff *hole = NULL; 2037 struct sk_buff *hole = NULL;
2038 u32 last_lost;
2038 int mib_idx; 2039 int mib_idx;
2039 int fwd_rexmitting = 0; 2040 int fwd_rexmitting = 0;
2040 2041
2041 if (!tp->lost_out) 2042 if (!tp->lost_out)
2042 tp->retransmit_high = tp->snd_una; 2043 tp->retransmit_high = tp->snd_una;
2043 2044
2044 if (tp->retransmit_skb_hint) 2045 if (tp->retransmit_skb_hint) {
2045 skb = tp->retransmit_skb_hint; 2046 skb = tp->retransmit_skb_hint;
2046 else 2047 last_lost = TCP_SKB_CB(skb)->end_seq;
2048 if (after(last_lost, tp->retransmit_high))
2049 last_lost = tp->retransmit_high;
2050 } else {
2047 skb = tcp_write_queue_head(sk); 2051 skb = tcp_write_queue_head(sk);
2052 last_lost = tp->snd_una;
2053 }
2048 2054
2049 /* First pass: retransmit lost packets. */ 2055 /* First pass: retransmit lost packets. */
2050 tcp_for_write_queue_from(skb, sk) { 2056 tcp_for_write_queue_from(skb, sk) {
@@ -2073,6 +2079,7 @@ begin_fwd:
2073 mib_idx = LINUX_MIB_TCPFORWARDRETRANS; 2079 mib_idx = LINUX_MIB_TCPFORWARDRETRANS;
2074 2080
2075 } else if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) { 2081 } else if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) {
2082 tp->retransmit_high = last_lost;
2076 if (!tcp_can_forward_retransmit(sk)) 2083 if (!tcp_can_forward_retransmit(sk))
2077 break; 2084 break;
2078 /* Backtrack if necessary to non-L'ed skb */ 2085 /* Backtrack if necessary to non-L'ed skb */
@@ -2089,6 +2096,7 @@ begin_fwd:
2089 continue; 2096 continue;
2090 2097
2091 } else { 2098 } else {
2099 last_lost = TCP_SKB_CB(skb)->end_seq;
2092 if (icsk->icsk_ca_state != TCP_CA_Loss) 2100 if (icsk->icsk_ca_state != TCP_CA_Loss)
2093 mib_idx = LINUX_MIB_TCPFASTRETRANS; 2101 mib_idx = LINUX_MIB_TCPFASTRETRANS;
2094 else 2102 else