diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2008-09-21 00:26:22 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-21 00:26:22 -0400 |
commit | 618d9f25548ba6fc3a9cd2ce5cd56f4f015b0635 (patch) | |
tree | f04a91ec4aac1fc4bcb0b8204a8ff64c3844e6de /net | |
parent | 90638a04ad8484b6b6c567656fb3f6d0689e23da (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')
-rw-r--r-- | net/ipv4/tcp_output.c | 12 |
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 |