From nobody Sun Feb 8 12:18:38 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 489CF1AAD2 for ; Mon, 4 Mar 2024 08:44:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709541860; cv=none; b=V7Sz+UvTpojxX91oxY4LLI4wMOovbqKQUoByBEldqA3RCMuhx809dOyar/K5eaXQ9AK1gPKO9rhkhw1vfyuVolVoi86CPUXO0buLEk4yFZ1F49Cd6AD4qDpGw6x44O7Jliv22uX3uJhz5fzR9S0FV3DMVvgeQ7Bso5+YDvxhb/Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709541860; c=relaxed/simple; bh=Hm+gxW/kHadxtc48yXaukCqMew6ym1016BnoNle9pNk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=X7B22MWeTsEBFwaaBSRaQUduztsGq5ZSea4ZlEtsFUY6NEG/YYNb5vhRLwHMBtfQU120y7sCnTCuvqt7WBUmFzPKiBlcBeHw5GMzvmXhwiLrxIgiRh43PGfXaV+KvaX4J/UznblX/4ARGeeKT4xztg1P1vhZq5XnZjM2wpSQzdA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=TSiyEfq2; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="TSiyEfq2" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1709541857; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UXvJfV7xY8fIppX1WMGYdHo1z+U7+tMRhsEec3It9fE=; b=TSiyEfq2J76/wDNqUS3bKvbwdH8NTiA5UenEMPanyZhDHmt+GLIprmxRS5dSnam+sGFi6y c2gtv8P4Jy1BORUaNpmCnFSefIR6lTaGXSpqv4TGkozGQS4FLB638Pi217xqJ/qrcC/PIG yg0n3E7yVjD/D9TXA4pjfheWIfwXXzY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-651-Oe7E2GaqM4eeeZsLRGrRHg-1; Mon, 04 Mar 2024 03:44:13 -0500 X-MC-Unique: Oe7E2GaqM4eeeZsLRGrRHg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6BE968489A0; Mon, 4 Mar 2024 08:44:13 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.114]) by smtp.corp.redhat.com (Postfix) with ESMTP id E0A7F24D; Mon, 4 Mar 2024 08:44:11 +0000 (UTC) From: David Howells To: netdev@vger.kernel.org Cc: David Howells , Marc Dionne , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 20/21] rxrpc: Clean up the resend algorithm Date: Mon, 4 Mar 2024 08:43:17 +0000 Message-ID: <20240304084322.705539-21-dhowells@redhat.com> In-Reply-To: <20240304084322.705539-1-dhowells@redhat.com> References: <20240304084322.705539-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 Content-Type: text/plain; charset="utf-8" Clean up the DATA packet resending algorithm to retransmit packets as we come across them whilst walking the transmission buffer rather than queuing them for retransmission at the end. This can be done as ACK parsing - and thus the discarding of successful packets - is now done in the same thread rather than separately in softirq context and a locked section is no longer required. Signed-off-by: David Howells cc: Marc Dionne cc: "David S. Miller" cc: Eric Dumazet cc: Jakub Kicinski cc: Paolo Abeni cc: linux-afs@lists.infradead.org cc: netdev@vger.kernel.org --- net/rxrpc/call_event.c | 79 ++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c index 2a9f74eb7c46..6c5e3054209b 100644 --- a/net/rxrpc/call_event.c +++ b/net/rxrpc/call_event.c @@ -71,23 +71,18 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_bu= ff *ack_skb) struct rxrpc_skb_priv *sp; struct rxrpc_txbuf *txb; rxrpc_seq_t transmitted =3D call->tx_transmitted; - ktime_t now, max_age, oldest, ack_ts, delay; - bool unacked =3D false; + ktime_t next_resend =3D KTIME_MAX, rto =3D ns_to_ktime(call->peer->rto_us= * NSEC_PER_USEC); + ktime_t resend_at =3D KTIME_MAX, now, delay; + bool unacked =3D false, did_send =3D false; unsigned int i; - LIST_HEAD(retrans_queue); =20 _enter("{%d,%d}", call->acks_hard_ack, call->tx_top); =20 now =3D ktime_get_real(); - max_age =3D ktime_sub_us(now, call->peer->rto_us); - oldest =3D now; =20 if (list_empty(&call->tx_buffer)) goto no_resend; =20 - if (list_empty(&call->tx_buffer)) - goto no_further_resend; - trace_rxrpc_resend(call, ack_skb); txb =3D list_first_entry(&call->tx_buffer, struct rxrpc_txbuf, call_link); =20 @@ -115,19 +110,23 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_= buff *ack_skb) goto no_further_resend; =20 found_txb: - if (after(txb->serial, call->acks_highest_serial)) + resend_at =3D ktime_add(txb->last_sent, rto); + if (after(txb->serial, call->acks_highest_serial)) { + if (ktime_after(resend_at, now) && + ktime_before(resend_at, next_resend)) + next_resend =3D resend_at; continue; /* Ack point not yet reached */ + } =20 rxrpc_see_txbuf(txb, rxrpc_txbuf_see_unacked); =20 - if (list_empty(&txb->tx_link)) { - list_add_tail(&txb->tx_link, &retrans_queue); - txb->flags |=3D RXRPC_TXBUF_RESENT; - } - trace_rxrpc_retransmit(call, txb->seq, txb->serial, - ktime_to_ns(ktime_sub(txb->last_sent, - max_age))); + ktime_sub(resend_at, now)); + + txb->flags |=3D RXRPC_TXBUF_RESENT; + rxrpc_transmit_one(call, txb); + did_send =3D true; + now =3D ktime_get_real(); =20 if (list_is_last(&txb->call_link, &call->tx_buffer)) goto no_further_resend; @@ -144,6 +143,8 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_bu= ff *ack_skb) goto no_further_resend; =20 list_for_each_entry_from(txb, &call->tx_buffer, call_link) { + resend_at =3D ktime_add(txb->last_sent, rto); + if (before_eq(txb->seq, call->acks_prev_seq)) continue; if (after(txb->seq, call->tx_transmitted)) @@ -153,25 +154,30 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_= buff *ack_skb) before(txb->serial, ntohl(ack->serial))) goto do_resend; /* Wasn't accounted for by a more recent ping. */ =20 - if (ktime_after(txb->last_sent, max_age)) { - if (ktime_before(txb->last_sent, oldest)) - oldest =3D txb->last_sent; + if (ktime_after(resend_at, now)) { + if (ktime_before(resend_at, next_resend)) + next_resend =3D resend_at; continue; } =20 do_resend: unacked =3D true; - if (list_empty(&txb->tx_link)) { - list_add_tail(&txb->tx_link, &retrans_queue); - txb->flags |=3D RXRPC_TXBUF_RESENT; - rxrpc_inc_stat(call->rxnet, stat_tx_data_retrans); - } + + txb->flags |=3D RXRPC_TXBUF_RESENT; + rxrpc_transmit_one(call, txb); + did_send =3D true; + rxrpc_inc_stat(call->rxnet, stat_tx_data_retrans); + now =3D ktime_get_real(); } =20 no_further_resend: no_resend: - delay =3D rxrpc_get_rto_backoff(call->peer, !list_empty(&retrans_queue)); - call->resend_at =3D ktime_add(oldest, delay); + if (resend_at < KTIME_MAX) { + delay =3D rxrpc_get_rto_backoff(call->peer, did_send); + resend_at =3D ktime_add(resend_at, delay); + trace_rxrpc_timer_set(call, resend_at - now, rxrpc_timer_trace_resend_re= set); + } + call->resend_at =3D resend_at; =20 if (unacked) rxrpc_congestion_timeout(call); @@ -180,24 +186,15 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_= buff *ack_skb) * that an ACK got lost somewhere. Send a ping to find out instead of * retransmitting data. */ - if (list_empty(&retrans_queue)) { - trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_resend_reset); - ack_ts =3D ktime_sub(now, call->acks_latest_ts); - if (ktime_to_us(ack_ts) < (call->peer->srtt_us >> 3)) - goto out; - rxrpc_send_ACK(call, RXRPC_ACK_PING, 0, - rxrpc_propose_ack_ping_for_0_retrans); - goto out; - } + if (!did_send) { + ktime_t next_ping =3D ktime_add_us(call->acks_latest_ts, + call->peer->srtt_us >> 3); =20 - /* Retransmit the queue */ - while ((txb =3D list_first_entry_or_null(&retrans_queue, - struct rxrpc_txbuf, tx_link))) { - list_del_init(&txb->tx_link); - rxrpc_transmit_one(call, txb); + if (ktime_sub(next_ping, now) <=3D 0) + rxrpc_send_ACK(call, RXRPC_ACK_PING, 0, + rxrpc_propose_ack_ping_for_0_retrans); } =20 -out: _leave(""); }