diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2008-09-21 00:24:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-21 00:24:21 -0400 |
commit | 0e1c54c2a405494281e0639aacc90db03b50ae77 (patch) | |
tree | ba5098bdf80603d4b5aa74af11738620f2ea7681 /net/ipv4/tcp_output.c | |
parent | 08ebd1721ab8fd362e90ae17b461c07b23fa2824 (diff) |
tcp: reorganize retransmit code loops
Both loops are quite similar, so they can be combined
with little effort. As a result, forward_skb_hint becomes
obsolete as well.
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.c | 79 |
1 files changed, 33 insertions, 46 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 9f44be633ef6..b5b4ddcdda41 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -2032,7 +2032,9 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
2032 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2032 | const struct inet_connection_sock *icsk = inet_csk(sk); |
2033 | struct tcp_sock *tp = tcp_sk(sk); | 2033 | struct tcp_sock *tp = tcp_sk(sk); |
2034 | struct sk_buff *skb; | 2034 | struct sk_buff *skb; |
2035 | struct sk_buff *hole = NULL; | ||
2035 | int mib_idx; | 2036 | int mib_idx; |
2037 | int fwd_rexmitting = 0; | ||
2036 | 2038 | ||
2037 | if (!tp->lost_out) | 2039 | if (!tp->lost_out) |
2038 | tp->retransmit_high = tp->snd_una; | 2040 | tp->retransmit_high = tp->snd_una; |
@@ -2049,7 +2051,8 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
2049 | if (skb == tcp_send_head(sk)) | 2051 | if (skb == tcp_send_head(sk)) |
2050 | break; | 2052 | break; |
2051 | /* we could do better than to assign each time */ | 2053 | /* we could do better than to assign each time */ |
2052 | tp->retransmit_skb_hint = skb; | 2054 | if (hole == NULL) |
2055 | tp->retransmit_skb_hint = skb; | ||
2053 | 2056 | ||
2054 | /* Assume this retransmit will generate | 2057 | /* Assume this retransmit will generate |
2055 | * only one packet for congestion window | 2058 | * only one packet for congestion window |
@@ -2060,65 +2063,49 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
2060 | */ | 2063 | */ |
2061 | if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) | 2064 | if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) |
2062 | return; | 2065 | return; |
2063 | if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) | ||
2064 | break; | ||
2065 | if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) | ||
2066 | continue; | ||
2067 | |||
2068 | if (!(sacked & TCPCB_LOST)) | ||
2069 | continue; | ||
2070 | |||
2071 | if (tcp_retransmit_skb(sk, skb)) { | ||
2072 | tp->retransmit_skb_hint = NULL; | ||
2073 | return; | ||
2074 | } | ||
2075 | if (icsk->icsk_ca_state != TCP_CA_Loss) | ||
2076 | mib_idx = LINUX_MIB_TCPFASTRETRANS; | ||
2077 | else | ||
2078 | mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; | ||
2079 | NET_INC_STATS_BH(sock_net(sk), mib_idx); | ||
2080 | |||
2081 | if (skb == tcp_write_queue_head(sk)) | ||
2082 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | ||
2083 | inet_csk(sk)->icsk_rto, | ||
2084 | TCP_RTO_MAX); | ||
2085 | } | ||
2086 | |||
2087 | /* OK, demanded retransmission is finished. */ | ||
2088 | if (!tcp_can_forward_retransmit(sk)) | ||
2089 | return; | ||
2090 | 2066 | ||
2091 | if (tp->forward_skb_hint) | 2067 | if (fwd_rexmitting) { |
2092 | skb = tp->forward_skb_hint; | 2068 | begin_fwd: |
2093 | else | 2069 | if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp))) |
2094 | skb = tcp_write_queue_head(sk); | 2070 | break; |
2071 | mib_idx = LINUX_MIB_TCPFORWARDRETRANS; | ||
2095 | 2072 | ||
2096 | tcp_for_write_queue_from(skb, sk) { | 2073 | } else if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) { |
2097 | if (skb == tcp_send_head(sk)) | 2074 | if (!tcp_can_forward_retransmit(sk)) |
2098 | break; | 2075 | break; |
2099 | tp->forward_skb_hint = skb; | 2076 | /* Backtrack if necessary to non-L'ed skb */ |
2077 | if (hole != NULL) { | ||
2078 | skb = hole; | ||
2079 | hole = NULL; | ||
2080 | } | ||
2081 | fwd_rexmitting = 1; | ||
2082 | goto begin_fwd; | ||
2100 | 2083 | ||
2101 | if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp))) | 2084 | } else if (!(sacked & TCPCB_LOST)) { |
2102 | break; | 2085 | if (hole == NULL && !(sacked & TCPCB_SACKED_RETRANS)) |
2086 | hole = skb; | ||
2087 | continue; | ||
2103 | 2088 | ||
2104 | if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) | 2089 | } else { |
2105 | break; | 2090 | if (icsk->icsk_ca_state != TCP_CA_Loss) |
2091 | mib_idx = LINUX_MIB_TCPFASTRETRANS; | ||
2092 | else | ||
2093 | mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; | ||
2094 | } | ||
2106 | 2095 | ||
2107 | if (TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS) | 2096 | if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) |
2108 | continue; | 2097 | continue; |
2109 | 2098 | ||
2110 | /* Ok, retransmit it. */ | ||
2111 | if (tcp_retransmit_skb(sk, skb)) { | 2099 | if (tcp_retransmit_skb(sk, skb)) { |
2112 | tp->forward_skb_hint = NULL; | 2100 | tp->retransmit_skb_hint = NULL; |
2113 | break; | 2101 | return; |
2114 | } | 2102 | } |
2103 | NET_INC_STATS_BH(sock_net(sk), mib_idx); | ||
2115 | 2104 | ||
2116 | if (skb == tcp_write_queue_head(sk)) | 2105 | if (skb == tcp_write_queue_head(sk)) |
2117 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | 2106 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, |
2118 | inet_csk(sk)->icsk_rto, | 2107 | inet_csk(sk)->icsk_rto, |
2119 | TCP_RTO_MAX); | 2108 | TCP_RTO_MAX); |
2120 | |||
2121 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFORWARDRETRANS); | ||
2122 | } | 2109 | } |
2123 | } | 2110 | } |
2124 | 2111 | ||