Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e1c54c2 authored by Ilpo Järvinen's avatar Ilpo Järvinen Committed by David S. Miller
Browse files

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: default avatarIlpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 08ebd172
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -342,7 +342,6 @@ struct tcp_sock {
	struct sk_buff* lost_skb_hint;
	struct sk_buff* lost_skb_hint;
	struct sk_buff *scoreboard_skb_hint;
	struct sk_buff *scoreboard_skb_hint;
	struct sk_buff *retransmit_skb_hint;
	struct sk_buff *retransmit_skb_hint;
	struct sk_buff *forward_skb_hint;


	struct sk_buff_head	out_of_order_queue; /* Out of order segments go here */
	struct sk_buff_head	out_of_order_queue; /* Out of order segments go here */


+0 −1
Original line number Original line Diff line number Diff line
@@ -1042,7 +1042,6 @@ static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp)
	tp->lost_skb_hint = NULL;
	tp->lost_skb_hint = NULL;
	tp->scoreboard_skb_hint = NULL;
	tp->scoreboard_skb_hint = NULL;
	tp->retransmit_skb_hint = NULL;
	tp->retransmit_skb_hint = NULL;
	tp->forward_skb_hint = NULL;
}
}


/* MD5 Signature */
/* MD5 Signature */
+33 −46
Original line number Original line Diff line number Diff line
@@ -2032,7 +2032,9 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
	const struct inet_connection_sock *icsk = inet_csk(sk);
	const struct inet_connection_sock *icsk = inet_csk(sk);
	struct tcp_sock *tp = tcp_sk(sk);
	struct tcp_sock *tp = tcp_sk(sk);
	struct sk_buff *skb;
	struct sk_buff *skb;
	struct sk_buff *hole = NULL;
	int mib_idx;
	int mib_idx;
	int fwd_rexmitting = 0;


	if (!tp->lost_out)
	if (!tp->lost_out)
		tp->retransmit_high = tp->snd_una;
		tp->retransmit_high = tp->snd_una;
@@ -2049,6 +2051,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
		if (skb == tcp_send_head(sk))
		if (skb == tcp_send_head(sk))
			break;
			break;
		/* we could do better than to assign each time */
		/* we could do better than to assign each time */
		if (hole == NULL)
			tp->retransmit_skb_hint = skb;
			tp->retransmit_skb_hint = skb;


		/* Assume this retransmit will generate
		/* Assume this retransmit will generate
@@ -2060,65 +2063,49 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
		 */
		 */
		if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
		if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
			return;
			return;
		if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high))

		if (fwd_rexmitting) {
begin_fwd:
			if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp)))
				break;
				break;
		if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))
			mib_idx = LINUX_MIB_TCPFORWARDRETRANS;
			continue;


		if (!(sacked & TCPCB_LOST))
		} 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;

		} else if (!(sacked & TCPCB_LOST)) {
			if (hole == NULL && !(sacked & TCPCB_SACKED_RETRANS))
				hole = skb;
			continue;
			continue;


		if (tcp_retransmit_skb(sk, skb)) {
		} else {
			tp->retransmit_skb_hint = NULL;
			return;
		}
			if (icsk->icsk_ca_state != TCP_CA_Loss)
			if (icsk->icsk_ca_state != TCP_CA_Loss)
				mib_idx = LINUX_MIB_TCPFASTRETRANS;
				mib_idx = LINUX_MIB_TCPFASTRETRANS;
			else
			else
				mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS;
				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 (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))
	if (!tcp_can_forward_retransmit(sk))
		return;

	if (tp->forward_skb_hint)
		skb = tp->forward_skb_hint;
	else
		skb = tcp_write_queue_head(sk);

	tcp_for_write_queue_from(skb, sk) {
		if (skb == tcp_send_head(sk))
			break;
		tp->forward_skb_hint = skb;

		if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp)))
			break;

		if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
			break;

		if (TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS)
			continue;
			continue;


		/* Ok, retransmit it. */
		if (tcp_retransmit_skb(sk, skb)) {
		if (tcp_retransmit_skb(sk, skb)) {
			tp->forward_skb_hint = NULL;
			tp->retransmit_skb_hint = NULL;
			break;
			return;
		}
		}
		NET_INC_STATS_BH(sock_net(sk), mib_idx);


		if (skb == tcp_write_queue_head(sk))
		if (skb == tcp_write_queue_head(sk))
			inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
			inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
						  inet_csk(sk)->icsk_rto,
						  inet_csk(sk)->icsk_rto,
						  TCP_RTO_MAX);
						  TCP_RTO_MAX);

		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFORWARDRETRANS);
	}
	}
}
}