diff options
| author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2008-09-20 21:24:21 -0700 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-09-20 21:24:21 -0700 | 
| commit | 0e1c54c2a405494281e0639aacc90db03b50ae77 (patch) | |
| tree | ba5098bdf80603d4b5aa74af11738620f2ea7681 /net/ipv4/tcp_output.c | |
| parent | 08ebd1721ab8fd362e90ae17b461c07b23fa2824 (diff) | |
| download | olio-linux-3.10-0e1c54c2a405494281e0639aacc90db03b50ae77.tar.xz olio-linux-3.10-0e1c54c2a405494281e0639aacc90db03b50ae77.zip  | |
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 9f44be633ef..b5b4ddcdda4 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)  	const struct inet_connection_sock *icsk = inet_csk(sk);  	struct tcp_sock *tp = tcp_sk(sk);  	struct sk_buff *skb; +	struct sk_buff *hole = NULL;  	int mib_idx; +	int fwd_rexmitting = 0;  	if (!tp->lost_out)  		tp->retransmit_high = tp->snd_una; @@ -2049,7 +2051,8 @@ void tcp_xmit_retransmit_queue(struct sock *sk)  		if (skb == tcp_send_head(sk))  			break;  		/* we could do better than to assign each time */ -		tp->retransmit_skb_hint = skb; +		if (hole == NULL) +			tp->retransmit_skb_hint = skb;  		/* Assume this retransmit will generate  		 * only one packet for congestion window @@ -2060,65 +2063,49 @@ void tcp_xmit_retransmit_queue(struct sock *sk)  		 */  		if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)  			return; -		if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) -			break; -		if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) -			continue; - -		if (!(sacked & TCPCB_LOST)) -			continue; - -		if (tcp_retransmit_skb(sk, skb)) { -			tp->retransmit_skb_hint = NULL; -			return; -		} -		if (icsk->icsk_ca_state != TCP_CA_Loss) -			mib_idx = LINUX_MIB_TCPFASTRETRANS; -		else -			mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; -		NET_INC_STATS_BH(sock_net(sk), mib_idx); - -		if (skb == tcp_write_queue_head(sk)) -			inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, -						  inet_csk(sk)->icsk_rto, -						  TCP_RTO_MAX); -	} - -	/* OK, demanded retransmission is finished. */ -	if (!tcp_can_forward_retransmit(sk)) -		return; -	if (tp->forward_skb_hint) -		skb = tp->forward_skb_hint; -	else -		skb = tcp_write_queue_head(sk); +		if (fwd_rexmitting) { +begin_fwd: +			if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp))) +				break; +			mib_idx = LINUX_MIB_TCPFORWARDRETRANS; -	tcp_for_write_queue_from(skb, sk) { -		if (skb == tcp_send_head(sk)) -			break; -		tp->forward_skb_hint = skb; +		} else if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) { +			if (!tcp_can_forward_retransmit(sk)) +				break; +			/* Backtrack if necessary to non-L'ed skb */ +			if (hole != NULL) { +				skb = hole; +				hole = NULL; +			} +			fwd_rexmitting = 1; +			goto begin_fwd; -		if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp))) -			break; +		} else if (!(sacked & TCPCB_LOST)) { +			if (hole == NULL && !(sacked & TCPCB_SACKED_RETRANS)) +				hole = skb; +			continue; -		if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) -			break; +		} else { +			if (icsk->icsk_ca_state != TCP_CA_Loss) +				mib_idx = LINUX_MIB_TCPFASTRETRANS; +			else +				mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; +		} -		if (TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS) +		if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))  			continue; -		/* Ok, retransmit it. */  		if (tcp_retransmit_skb(sk, skb)) { -			tp->forward_skb_hint = NULL; -			break; +			tp->retransmit_skb_hint = NULL; +			return;  		} +		NET_INC_STATS_BH(sock_net(sk), mib_idx);  		if (skb == tcp_write_queue_head(sk))  			inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,  						  inet_csk(sk)->icsk_rto,  						  TCP_RTO_MAX); - -		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFORWARDRETRANS);  	}  }  |