From patchwork Sat Sep 20 17:52:29 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ilpo_J=C3=A4rvinen?= X-Patchwork-Id: 734 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id 3CB75DDEED for ; Sun, 21 Sep 2008 03:53:15 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751549AbYITRxG (ORCPT ); Sat, 20 Sep 2008 13:53:06 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751535AbYITRxD (ORCPT ); Sat, 20 Sep 2008 13:53:03 -0400 Received: from courier.cs.helsinki.fi ([128.214.9.1]:49080 "EHLO mail.cs.helsinki.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751316AbYITRwl (ORCPT ); Sat, 20 Sep 2008 13:52:41 -0400 Received: from wrl-59.cs.helsinki.fi (wrl-59.cs.helsinki.fi [128.214.166.179]) (AUTH: PLAIN cs-relay, TLS: TLSv1/SSLv3,256bits,AES256-SHA) by mail.cs.helsinki.fi with esmtp; Sat, 20 Sep 2008 20:52:34 +0300 id 0005BEDF.48D53862.00002DB2 Received: by wrl-59.cs.helsinki.fi (Postfix, from userid 50795) id 909C9A00AB; Sat, 20 Sep 2008 20:52:34 +0300 (EEST) From: "=?ISO-8859-1?Q?Ilpo_J=E4rvinen?=" To: David Miller Cc: netdev@vger.kernel.org, "=?utf-8?q?Ilpo=20J=E4rvinen?=" Subject: [PATCH net-next 11/15] tcp: reorganize retransmit code loops Date: Sat, 20 Sep 2008 20:52:29 +0300 Message-Id: <1221933153-11874-12-git-send-email-ilpo.jarvinen@helsinki.fi> X-Mailer: git-send-email 1.5.4.2.156.ge3c5 In-Reply-To: <1221933153-11874-11-git-send-email-ilpo.jarvinen@helsinki.fi> References: <1221933153-11874-1-git-send-email-ilpo.jarvinen@helsinki.fi> <1221933153-11874-2-git-send-email-ilpo.jarvinen@helsinki.fi> <1221933153-11874-3-git-send-email-ilpo.jarvinen@helsinki.fi> <1221933153-11874-4-git-send-email-ilpo.jarvinen@helsinki.fi> <1221933153-11874-5-git-send-email-ilpo.jarvinen@helsinki.fi> <1221933153-11874-6-git-send-email-ilpo.jarvinen@helsinki.fi> <1221933153-11874-7-git-send-email-ilpo.jarvinen@helsinki.fi> <1221933153-11874-8-git-send-email-ilpo.jarvinen@helsinki.fi> <1221933153-11874-9-git-send-email-ilpo.jarvinen@helsinki.fi> <1221933153-11874-10-git-send-email-ilpo.jarvinen@helsinki.fi> <1221933153-11874-11-git-send-email-ilpo.jarvinen@helsinki.fi> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Both loops are quite similar, so they can be combined with little effort. As a result, forward_skb_hint becomes obsolete as well. Since non-fwd rexmissions have priority over the fwd-rexmits (not that this is written to some stone that it should be so, it's just the current behavior and I currently see no reason to change that), some trickery had to implemented to keep skb hint never going past a hole so that we can return there if that becomes later on necessary. Signed-off-by: Ilpo Järvinen --- include/linux/tcp.h | 1 - include/net/tcp.h | 1 - net/ipv4/tcp_output.c | 79 ++++++++++++++++++++---------------------------- 3 files changed, 33 insertions(+), 48 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index d7637c4..7672906 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -342,7 +342,6 @@ struct tcp_sock { struct sk_buff* lost_skb_hint; struct sk_buff *scoreboard_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 */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 9be41c9..10f838e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1041,7 +1041,6 @@ static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp) tp->lost_skb_hint = NULL; tp->scoreboard_skb_hint = NULL; tp->retransmit_skb_hint = NULL; - tp->forward_skb_hint = NULL; } extern void tcp_verify_retransmit_hint(struct tcp_sock *tp, diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index fc7bfd6..0234b6f 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2034,7 +2034,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; @@ -2051,7 +2053,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 @@ -2062,65 +2065,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); } }