From: David Howells <dhowells@redhat.com>
To: netdev@vger.kernel.org
Cc: David Howells <dhowells@redhat.com>,
Marc Dionne <marc.dionne@auristor.com>,
Jakub Kicinski <kuba@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org,
Jeffrey Altman <jaltman@auristor.com>,
stable@vger.kernel.org
Subject: [PATCH net v2 2/3] rxrpc: Fix counting of in-flight transmitted packets
Date: Tue, 20 Oct 2026 21:12:53 +0100 [thread overview]
Message-ID: <20261020201258.290827-3-dhowells@redhat.com> (raw)
In-Reply-To: <20261020201258.290827-1-dhowells@redhat.com>
The RACK-TLP algorithm [RFC8985] makes use of the count of in-flight
packets in decisions (denoted as FlightSize). This is currently based on
an approximation derived from the sum of other values:
tx_nr_sent - (acks_nr_sacks + tx_nr_lost) + tx_nr_resent
This, however, turns out not to be very good here as the component counters
aren't updated together and this may lead to an incorrect estimate.
Fix counting of in-flight transmitted packets by tracking them directly
rather than deriving the value:
(1) On each rxrpc_txqueue struct, keep a bitmap of which packets (txbuf)
from the set managed by that txqueue are considered in-flight.
(2) A new counter, tx_in_flight, is then added to the rxrpc_call struct to
keep track of the number of packets considered to be in flight.
(3) Set a packet's bit when the packet is transmitted and if the bit
wasn't already set, increment tx_in_flight.
(4) Clear a packet's bit when an ACK is received for the packet or if the
packet is declared lost - and if the bit wasn't already cleared,
decrement tx_in_flight.
The value in tx_in_flight is then used instead of the approximation.
The tx_nr_sent and tx_nr_resent counters are then removed and the
rxrpc_rack tracepoint updated.
Fixes: 7c482665931b ("rxrpc: Implement RACK/TLP to deal with transmission stalls [RFC8985]")
Link: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260925191520.2206700-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@vger.kernel.org
---
include/trace/events/rxrpc.h | 11 ++++-------
net/rxrpc/ar-internal.h | 18 ++----------------
net/rxrpc/input.c | 8 ++++----
net/rxrpc/input_rack.c | 19 +++++++++++--------
net/rxrpc/output.c | 5 +++--
5 files changed, 24 insertions(+), 37 deletions(-)
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 56dc9b614071..67a5612cdc55 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -2584,9 +2584,8 @@ TRACE_EVENT(rxrpc_rack,
__field(rxrpc_serial_t, ack_serial)
__field(rxrpc_seq_t, seq)
__field(enum rxrpc_rack_timer_mode, mode)
- __field(unsigned short, nr_sent)
+ __field(unsigned short, in_flight)
__field(unsigned short, nr_lost)
- __field(unsigned short, nr_resent)
__field(unsigned short, nr_sacked)
__field(ktime_t, timo)
),
@@ -2596,18 +2595,16 @@ TRACE_EVENT(rxrpc_rack,
__entry->ack_serial = call->rx_serial;
__entry->seq = call->rack_end_seq;
__entry->mode = call->rack_timer_mode;
- __entry->nr_sent = call->tx_nr_sent;
+ __entry->in_flight = call->tx_in_flight;
__entry->nr_lost = call->tx_nr_lost;
- __entry->nr_resent = call->tx_nr_resent;
__entry->nr_sacked = call->acks_nr_sacks;
__entry->timo = timo;
),
- TP_printk("c=%08x r=%08x q=%08x %s slrs=%u,%u,%u,%u t=%lld",
+ TP_printk("c=%08x r=%08x q=%08x %s fls=%u,%u,%u t=%lld",
__entry->call, __entry->ack_serial, __entry->seq,
__print_symbolic(__entry->mode, rxrpc_rack_timer_modes),
- __entry->nr_sent, __entry->nr_lost,
- __entry->nr_resent, __entry->nr_sacked,
+ __entry->in_flight, __entry->nr_lost, __entry->nr_sacked,
ktime_to_us(__entry->timo))
);
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index f0c8cbcc5dd5..d0e18eb6301e 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -782,9 +782,8 @@ struct rxrpc_call {
rxrpc_seq_t tx_top; /* Highest Tx slot allocated. */
rxrpc_serial_t tx_last_serial; /* Serial of last DATA transmitted */
u16 tx_backoff; /* Delay to insert due to Tx failure (ms) */
- u16 tx_nr_sent; /* Number of packets sent, but unacked */
+ u16 tx_in_flight; /* Number of packets considered "in flight" */
u16 tx_nr_lost; /* Number of packets marked lost */
- u16 tx_nr_resent; /* Number of packets resent, but unacked */
u16 tx_winsize; /* Maximum size of Tx window */
#define RXRPC_TX_MAX_WINDOW 128
u8 tx_jumbo_max; /* Maximum subpkts peer will accept */
@@ -980,6 +979,7 @@ struct rxrpc_txqueue {
unsigned long segment_acked; /* Bit-per-buf: Set if ACK'd */
unsigned long segment_lost; /* Bit-per-buf: Set if declared lost */
unsigned long segment_retransmitted; /* Bit-per-buf: Set if retransmitted */
+ unsigned long in_flight; /* Bit-per-buf: Set if "in flight" */
unsigned long rtt_samples; /* Bit-per-buf: Set if available for RTT */
unsigned long ever_retransmitted; /* Bit-per-buf: Set if ever retransmitted */
@@ -1601,20 +1601,6 @@ static inline unsigned int rxrpc_tx_window_space(const struct rxrpc_call *call)
return max(winsize - transmitted, 0);
}
-static inline unsigned int rxrpc_left_out(const struct rxrpc_call *call)
-{
- return call->acks_nr_sacks + call->tx_nr_lost;
-}
-
-/*
- * Calculate the number of transmitted DATA packets assumed to be in flight
- * [approx RFC6675].
- */
-static inline unsigned int rxrpc_tx_in_flight(const struct rxrpc_call *call)
-{
- return call->tx_nr_sent - rxrpc_left_out(call) + call->tx_nr_resent;
-}
-
/*
* debug tracing
*/
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 73cafe6bfa9f..f497eba59cf6 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -33,7 +33,7 @@ static void rxrpc_congestion_management(struct rxrpc_call *call,
struct rxrpc_ack_summary *summary)
{
summary->change = rxrpc_cong_no_change;
- summary->in_flight = rxrpc_tx_in_flight(call);
+ summary->in_flight = call->tx_in_flight;
if (test_and_clear_bit(RXRPC_CALL_RETRANS_TIMEOUT, &call->flags)) {
summary->retrans_timeo = true;
@@ -288,11 +288,11 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
trace_rxrpc_rotate(call, tq, summary, seq, rxrpc_rotate_trace_snak);
}
- call->tx_nr_sent--;
+ if (__test_and_clear_bit(ix, &tq->in_flight))
+ call->tx_in_flight--;
if (__test_and_clear_bit(ix, &tq->segment_lost))
call->tx_nr_lost--;
- if (__test_and_clear_bit(ix, &tq->segment_retransmitted))
- call->tx_nr_resent--;
+ __clear_bit(ix, &tq->segment_retransmitted);
__clear_bit(ix, &tq->ever_retransmitted);
rxrpc_put_txbuf(tq->bufs[ix], rxrpc_txbuf_put_rotated);
diff --git a/net/rxrpc/input_rack.c b/net/rxrpc/input_rack.c
index 072e1d9ecb2e..e43ce032a261 100644
--- a/net/rxrpc/input_rack.c
+++ b/net/rxrpc/input_rack.c
@@ -23,12 +23,13 @@ static bool rxrpc_rack_sent_after(ktime_t t1, rxrpc_seq_t seq1,
static void rxrpc_rack_mark_lost(struct rxrpc_call *call,
struct rxrpc_txqueue *tq, unsigned int ix)
{
- if (__test_and_set_bit(ix, &tq->segment_lost)) {
- if (__test_and_clear_bit(ix, &tq->segment_retransmitted))
- call->tx_nr_resent--;
- } else {
+ if (__test_and_set_bit(ix, &tq->segment_lost))
+ __clear_bit(ix, &tq->segment_retransmitted);
+ else
call->tx_nr_lost++;
- }
+
+ if (__test_and_clear_bit(ix, &tq->in_flight))
+ call->tx_in_flight--;
tq->segment_xmit_ts[ix] = UINT_MAX;
}
@@ -136,6 +137,8 @@ void rxrpc_input_rack(struct rxrpc_call *call,
unsigned int ix = __ffs(new_acks);
__clear_bit(ix, &new_acks);
+ if (__test_and_clear_bit(ix, &tq->in_flight))
+ call->tx_in_flight--;
rxrpc_input_rack_one(call, summary, tq, ix);
}
@@ -289,7 +292,7 @@ static void rxrpc_rack_mark_losses_on_rto(struct rxrpc_call *call)
*/
ktime_t rxrpc_tlp_calc_pto(struct rxrpc_call *call, ktime_t now)
{
- unsigned int flight_size = rxrpc_tx_in_flight(call);
+ unsigned int flight_size = call->tx_in_flight;
ktime_t rto_at = ktime_add(call->tx_last_sent,
rxrpc_get_rto_backoff(call, false));
ktime_t pto;
@@ -313,7 +316,7 @@ ktime_t rxrpc_tlp_calc_pto(struct rxrpc_call *call, ktime_t now)
*/
void rxrpc_tlp_send_probe(struct rxrpc_call *call)
{
- unsigned int in_flight = rxrpc_tx_in_flight(call);
+ unsigned int in_flight = call->tx_in_flight;
if (after_eq(call->acks_hard_ack, call->tx_transmitted))
return; /* Everything we transmitted has been acked. */
@@ -333,7 +336,7 @@ void rxrpc_tlp_send_probe(struct rxrpc_call *call)
call->tlp_serial = call->tx_last_serial;
call->tlp_seq = call->tx_transmitted;
trace_rxrpc_tlp_probe(call, rxrpc_tlp_probe_trace_transmit_new);
- in_flight = rxrpc_tx_in_flight(call);
+ in_flight = call->tx_in_flight;
} else {
/* Retransmit the highest-sequence DATA sent */
call->tx_last_serial = 0;
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 88cad087f13b..3ccd9a27643a 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -571,15 +571,16 @@ static size_t rxrpc_prepare_data_packet(struct rxrpc_call *call,
_debug("prep[%u] tq=%x q=%x", i, tq->qbase, seq);
+ if (!__test_and_set_bit(ix, &tq->in_flight))
+ call->tx_in_flight++;
+
/* Record (re-)transmission for RACK [RFC8985 6.1]. */
if (__test_and_clear_bit(ix, &tq->segment_lost))
call->tx_nr_lost--;
if (req->retrans) {
__set_bit(ix, &tq->ever_retransmitted);
__set_bit(ix, &tq->segment_retransmitted);
- call->tx_nr_resent++;
} else {
- call->tx_nr_sent++;
start_tlp = true;
}
tq->segment_xmit_ts[ix] = xmit_ts;
next prev parent reply other threads:[~2026-10-20 20:13 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 20:12 [PATCH net v2 0/3] rxrpc: RACK-TLP fixes David Howells
2026-10-20 20:12 ` [PATCH net v2 1/3] rxrpc: Fix the comments saying RFC8958 to be RFC8985 David Howells
2026-10-20 20:12 ` David Howells [this message]
2026-10-20 20:12 ` [PATCH net v2 3/3] rxrpc: Fix RACK-TLP implementation David Howells
2026-10-20 20:19 ` [PATCH net v2 0/3] rxrpc: RACK-TLP fixes netdev-bot+sinfo
2026-10-21 6:10 ` David Howells
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261020201258.290827-3-dhowells@redhat.com \
--to=dhowells@redhat.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jaltman@auristor.com \
--cc=kuba@kernel.org \
--cc=linux-afs@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=marc.dionne@auristor.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.