From: David Howells <dhowells@redhat.com>
To: netdev@vger.kernel.org
Cc: David Howells <dhowells@redhat.com>,
Marc Dionne <marc.dionne@auristor.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
linux-afs@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: [PATCH net-next v2 19/21] rxrpc: Record probes after transmission and reduce number of time-gets
Date: Mon, 4 Mar 2024 08:43:16 +0000 [thread overview]
Message-ID: <20240304084322.705539-20-dhowells@redhat.com> (raw)
In-Reply-To: <20240304084322.705539-1-dhowells@redhat.com>
Move the recording of a successfully transmitted DATA or ACK packet that
will provide RTT probing to after the transmission. With the I/O thread
model, this can be done because parsing of the responding ACK can no longer
race with the post-transmission code.
Move the various timeout-settings done after successfully transmitting a
DATA packet into rxrpc_tstamp_data_packets() and eliminate a number of
calls to get the current time.
As a consequence we no longer need to cancel a proposed RTT probe on
transmission failure.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Eric Dumazet <edumazet@google.com>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
---
net/rxrpc/output.c | 105 +++++++++++++++++----------------------------
1 file changed, 40 insertions(+), 65 deletions(-)
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index ec82193e5681..5ea9601efd05 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -63,7 +63,7 @@ static void rxrpc_tx_backoff(struct rxrpc_call *call, int ret)
* Receiving a response to the ping will prevent the ->expect_rx_by timer from
* expiring.
*/
-static void rxrpc_set_keepalive(struct rxrpc_call *call)
+static void rxrpc_set_keepalive(struct rxrpc_call *call, ktime_t now)
{
ktime_t delay = ms_to_ktime(READ_ONCE(call->next_rx_timo) / 6);
@@ -147,8 +147,8 @@ static void rxrpc_fill_out_ack(struct rxrpc_call *call,
/*
* Record the beginning of an RTT probe.
*/
-static int rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t serial,
- enum rxrpc_rtt_tx_trace why)
+static void rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t serial,
+ ktime_t now, enum rxrpc_rtt_tx_trace why)
{
unsigned long avail = call->rtt_avail;
int rtt_slot = 9;
@@ -161,30 +161,15 @@ static int rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t serial,
goto no_slot;
call->rtt_serial[rtt_slot] = serial;
- call->rtt_sent_at[rtt_slot] = ktime_get_real();
+ call->rtt_sent_at[rtt_slot] = now;
smp_wmb(); /* Write data before avail bit */
set_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
trace_rxrpc_rtt_tx(call, why, rtt_slot, serial);
- return rtt_slot;
+ return;
no_slot:
trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_no_slot, rtt_slot, serial);
- return -1;
-}
-
-/*
- * Cancel an RTT probe.
- */
-static void rxrpc_cancel_rtt_probe(struct rxrpc_call *call,
- rxrpc_serial_t serial, int rtt_slot)
-{
- if (rtt_slot != -1) {
- clear_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
- smp_wmb(); /* Clear pending bit before setting slot */
- set_bit(rtt_slot, &call->rtt_avail);
- trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_cancel, rtt_slot, serial);
- }
}
/*
@@ -196,7 +181,8 @@ static void rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
struct rxrpc_connection *conn;
struct rxrpc_ackpacket *ack = (struct rxrpc_ackpacket *)(whdr + 1);
struct msghdr msg;
- int ret, rtt_slot = -1;
+ ktime_t now;
+ int ret;
if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
return;
@@ -218,9 +204,6 @@ static void rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
ntohl(ack->serial), ack->reason, ack->nAcks,
txb->ack_rwind);
- if (ack->reason == RXRPC_ACK_PING)
- rtt_slot = rxrpc_begin_rtt_probe(call, txb->serial, rxrpc_rtt_tx_ping);
-
rxrpc_inc_stat(call->rxnet, stat_tx_ack_send);
iov_iter_kvec(&msg.msg_iter, WRITE, txb->kvec, txb->nr_kvec, txb->len);
@@ -233,16 +216,14 @@ static void rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
} else {
trace_rxrpc_tx_packet(call->debug_id, whdr,
rxrpc_tx_point_call_ack);
+ now = ktime_get_real();
+ if (ack->reason == RXRPC_ACK_PING)
+ rxrpc_begin_rtt_probe(call, txb->serial, now, rxrpc_rtt_tx_ping);
if (txb->flags & RXRPC_REQUEST_ACK)
- call->peer->rtt_last_req = ktime_get_real();
+ call->peer->rtt_last_req = now;
+ rxrpc_set_keepalive(call, now);
}
rxrpc_tx_backoff(call, ret);
-
- if (!__rxrpc_call_is_complete(call)) {
- if (ret < 0)
- rxrpc_cancel_rtt_probe(call, txb->serial, rtt_slot);
- rxrpc_set_keepalive(call);
- }
}
/*
@@ -413,18 +394,36 @@ static size_t rxrpc_prepare_data_packet(struct rxrpc_call *call, struct rxrpc_tx
}
/*
- * Set the times on a packet before transmission
+ * Set timeouts after transmitting a packet.
*/
-static int rxrpc_tstamp_data_packets(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
+static void rxrpc_tstamp_data_packets(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
{
- ktime_t tstamp = ktime_get_real();
- int rtt_slot = -1;
+ ktime_t now = ktime_get_real();
+ bool ack_requested = txb->flags & RXRPC_REQUEST_ACK;
- txb->last_sent = tstamp;
- if (txb->flags & RXRPC_REQUEST_ACK)
- rtt_slot = rxrpc_begin_rtt_probe(call, txb->serial, rxrpc_rtt_tx_data);
+ call->tx_last_sent = now;
+ txb->last_sent = now;
+
+ if (ack_requested) {
+ rxrpc_begin_rtt_probe(call, txb->serial, now, rxrpc_rtt_tx_data);
+
+ call->peer->rtt_last_req = now;
+ if (call->peer->rtt_count > 1) {
+ ktime_t delay = rxrpc_get_rto_backoff(call->peer, false);
- return rtt_slot;
+ call->ack_lost_at = ktime_add(now, delay);
+ trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_lost_ack);
+ }
+ }
+
+ if (!test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER, &call->flags)) {
+ ktime_t delay = ms_to_ktime(READ_ONCE(call->next_rx_timo));
+
+ call->expect_rx_by = ktime_add(now, delay);
+ trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_expect_rx);
+ }
+
+ rxrpc_set_keepalive(call, now);
}
/*
@@ -437,7 +436,7 @@ static int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
enum rxrpc_tx_point frag;
struct msghdr msg;
size_t len;
- int ret, rtt_slot = -1;
+ int ret;
_enter("%x,{%d}", txb->seq, txb->len);
@@ -479,8 +478,6 @@ static int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
}
retry:
- rtt_slot = rxrpc_tstamp_data_packets(call, txb);
-
/* send the packet by UDP
* - returns -EMSGSIZE if UDP would have to fragment the packet
* to go out of the interface
@@ -493,7 +490,6 @@ static int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
if (ret < 0) {
rxrpc_inc_stat(call->rxnet, stat_tx_data_send_fail);
- rxrpc_cancel_rtt_probe(call, txb->serial, rtt_slot);
trace_rxrpc_tx_fail(call->debug_id, txb->serial, ret, frag);
} else {
trace_rxrpc_tx_packet(call->debug_id, whdr, frag);
@@ -508,28 +504,7 @@ static int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
done:
if (ret >= 0) {
- call->tx_last_sent = txb->last_sent;
- if (txb->flags & RXRPC_REQUEST_ACK) {
- call->peer->rtt_last_req = txb->last_sent;
- if (call->peer->rtt_count > 1) {
- ktime_t delay = rxrpc_get_rto_backoff(call->peer, false);
- ktime_t now = ktime_get_real();
-
- call->ack_lost_at = ktime_add(now, delay);
- trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_lost_ack);
- }
- }
-
- if (txb->seq == 1 &&
- !test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER,
- &call->flags)) {
- ktime_t delay = ms_to_ktime(READ_ONCE(call->next_rx_timo));
-
- call->expect_rx_by = ktime_add(ktime_get_real(), delay);
- trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_expect_rx);
- }
-
- rxrpc_set_keepalive(call);
+ rxrpc_tstamp_data_packets(call, txb);
} else {
/* Cancel the call if the initial transmission fails,
* particularly if that's due to network routing issues that
next prev parent reply other threads:[~2024-03-04 8:44 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-04 8:42 [PATCH net-next v2 00/21] rxrpc: Miscellaneous changes and make use of MSG_SPLICE_PAGES David Howells
2024-03-04 8:42 ` [PATCH net-next v2 01/21] rxrpc: Record the Tx serial in the rxrpc_txbuf and retransmit trace David Howells
2024-03-04 8:42 ` [PATCH net-next v2 02/21] rxrpc: Convert rxrpc_txbuf::flags into a mask and don't use atomics David Howells
2024-03-04 8:43 ` [PATCH net-next v2 03/21] rxrpc: Note cksum in txbuf David Howells
2024-03-04 8:43 ` [PATCH net-next v2 04/21] rxrpc: Fix the names of the fields in the ACK trailer struct David Howells
2024-03-04 8:43 ` [PATCH net-next v2 05/21] rxrpc: Strip barriers and atomics off of timer tracking David Howells
2024-03-04 8:43 ` [PATCH net-next v2 06/21] rxrpc: Remove atomic handling on some fields only used in I/O thread David Howells
2024-03-04 8:43 ` [PATCH net-next v2 07/21] rxrpc: Do lazy DF flag resetting David Howells
2024-03-04 8:43 ` [PATCH net-next v2 08/21] rxrpc: Merge together DF/non-DF branches of data Tx function David Howells
2024-03-04 8:43 ` [PATCH net-next v2 09/21] rxrpc: Add a kvec[] to the rxrpc_txbuf struct David Howells
2024-03-04 8:43 ` [PATCH net-next v2 10/21] rxrpc: Split up the DATA packet transmission function David Howells
2024-03-04 8:43 ` [PATCH net-next v2 11/21] rxrpc: Don't pick values out of the wire header when setting up security David Howells
2024-03-04 8:43 ` [PATCH net-next v2 12/21] rxrpc: Move rxrpc_send_ACK() to output.c with rxrpc_send_ack_packet() David Howells
2024-03-04 8:43 ` [PATCH net-next v2 13/21] rxrpc: Use rxrpc_txbuf::kvec[0] instead of rxrpc_txbuf::wire David Howells
2024-03-04 8:43 ` [PATCH net-next v2 14/21] rxrpc: Do zerocopy using MSG_SPLICE_PAGES and page frags David Howells
2024-03-05 14:03 ` Simon Horman
2024-03-04 8:43 ` [PATCH net-next v2 15/21] rxrpc: Parse received packets before dealing with timeouts David Howells
2024-03-04 8:43 ` [PATCH net-next v2 16/21] rxrpc: Don't permit resending after all Tx packets acked David Howells
2024-03-04 8:43 ` [PATCH net-next v2 17/21] rxrpc: Differentiate PING ACK transmission traces David Howells
2024-03-04 8:43 ` [PATCH net-next v2 18/21] rxrpc: Use ktimes for call timeout tracking and set the timer lazily David Howells
2024-03-04 8:43 ` David Howells [this message]
2024-03-04 8:43 ` [PATCH net-next v2 20/21] rxrpc: Clean up the resend algorithm David Howells
2024-03-04 8:43 ` [PATCH net-next v2 21/21] rxrpc: Extract useful fields from a received ACK to skb priv data 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=20240304084322.705539-20-dhowells@redhat.com \
--to=dhowells@redhat.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.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 \
/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.