aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_output.c
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2008-09-21 00:24:21 -0400
committerDavid S. Miller <davem@davemloft.net>2008-09-21 00:24:21 -0400
commit0e1c54c2a405494281e0639aacc90db03b50ae77 (patch)
treeba5098bdf80603d4b5aa74af11738620f2ea7681 /net/ipv4/tcp_output.c
parent08ebd1721ab8fd362e90ae17b461c07b23fa2824 (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.c79
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; 2068begin_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