Skip to content

Commit 50235c4

Browse files
committed
rxrpc: Obtain RTT data by requesting ACKs on DATA packets
In addition to sending a PING ACK to gain RTT data, we can set the RXRPC_REQUEST_ACK flag on a DATA packet and get a REQUESTED-ACK ACK. The ACK packet contains the serial number of the packet it is in response to, so we can look through the Tx buffer for a matching DATA packet. This requires that the data packets be stamped with the time of transmission as a ktime rather than having the resend_at time in jiffies. This further requires the resend code to do the resend determination in ktimes and convert to jiffies to set the timer. Signed-off-by: David Howells <[email protected]>
1 parent 77f2efc commit 50235c4

File tree

7 files changed

+57
-20
lines changed

7 files changed

+57
-20
lines changed

net/rxrpc/ar-internal.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,7 @@ struct rxrpc_host_header {
142142
*/
143143
struct rxrpc_skb_priv {
144144
union {
145-
unsigned long resend_at; /* time in jiffies at which to resend */
146-
struct {
147-
u8 nr_jumbo; /* Number of jumbo subpackets */
148-
};
145+
u8 nr_jumbo; /* Number of jumbo subpackets */
149146
};
150147
union {
151148
unsigned int offset; /* offset into buffer of next read */
@@ -663,13 +660,15 @@ extern const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5];
663660

664661
enum rxrpc_rtt_tx_trace {
665662
rxrpc_rtt_tx_ping,
663+
rxrpc_rtt_tx_data,
666664
rxrpc_rtt_tx__nr_trace
667665
};
668666

669667
extern const char rxrpc_rtt_tx_traces[rxrpc_rtt_tx__nr_trace][5];
670668

671669
enum rxrpc_rtt_rx_trace {
672670
rxrpc_rtt_rx_ping_response,
671+
rxrpc_rtt_rx_requested_ack,
673672
rxrpc_rtt_rx__nr_trace
674673
};
675674

net/rxrpc/call_event.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,14 @@ static void rxrpc_resend(struct rxrpc_call *call)
142142
struct rxrpc_skb_priv *sp;
143143
struct sk_buff *skb;
144144
rxrpc_seq_t cursor, seq, top;
145-
unsigned long resend_at, now;
145+
ktime_t now = ktime_get_real(), max_age, oldest, resend_at;
146146
int ix;
147147
u8 annotation, anno_type;
148148

149149
_enter("{%d,%d}", call->tx_hard_ack, call->tx_top);
150150

151+
max_age = ktime_sub_ms(now, rxrpc_resend_timeout);
152+
151153
spin_lock_bh(&call->lock);
152154

153155
cursor = call->tx_hard_ack;
@@ -160,8 +162,7 @@ static void rxrpc_resend(struct rxrpc_call *call)
160162
* the packets in the Tx buffer we're going to resend and what the new
161163
* resend timeout will be.
162164
*/
163-
now = jiffies;
164-
resend_at = now + rxrpc_resend_timeout;
165+
oldest = now;
165166
for (seq = cursor + 1; before_eq(seq, top); seq++) {
166167
ix = seq & RXRPC_RXTX_BUFF_MASK;
167168
annotation = call->rxtx_annotations[ix];
@@ -175,9 +176,9 @@ static void rxrpc_resend(struct rxrpc_call *call)
175176
sp = rxrpc_skb(skb);
176177

177178
if (anno_type == RXRPC_TX_ANNO_UNACK) {
178-
if (time_after(sp->resend_at, now)) {
179-
if (time_before(sp->resend_at, resend_at))
180-
resend_at = sp->resend_at;
179+
if (ktime_after(skb->tstamp, max_age)) {
180+
if (ktime_before(skb->tstamp, oldest))
181+
oldest = skb->tstamp;
181182
continue;
182183
}
183184
}
@@ -186,7 +187,8 @@ static void rxrpc_resend(struct rxrpc_call *call)
186187
call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation;
187188
}
188189

189-
call->resend_at = resend_at;
190+
resend_at = ktime_sub(ktime_add_ns(oldest, rxrpc_resend_timeout), now);
191+
call->resend_at = jiffies + nsecs_to_jiffies(ktime_to_ns(resend_at));
190192

191193
/* Now go through the Tx window and perform the retransmissions. We
192194
* have to drop the lock for each send. If an ACK comes in whilst the
@@ -205,15 +207,12 @@ static void rxrpc_resend(struct rxrpc_call *call)
205207
spin_unlock_bh(&call->lock);
206208

207209
if (rxrpc_send_data_packet(call, skb) < 0) {
208-
call->resend_at = now + 2;
209210
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
210211
return;
211212
}
212213

213214
if (rxrpc_is_client_call(call))
214215
rxrpc_expose_client_call(call);
215-
sp = rxrpc_skb(skb);
216-
sp->resend_at = now + rxrpc_resend_timeout;
217216

218217
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
219218
spin_lock_bh(&call->lock);

net/rxrpc/input.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,38 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
355355
_leave(" [queued]");
356356
}
357357

358+
/*
359+
* Process a requested ACK.
360+
*/
361+
static void rxrpc_input_requested_ack(struct rxrpc_call *call,
362+
ktime_t resp_time,
363+
rxrpc_serial_t orig_serial,
364+
rxrpc_serial_t ack_serial)
365+
{
366+
struct rxrpc_skb_priv *sp;
367+
struct sk_buff *skb;
368+
ktime_t sent_at;
369+
int ix;
370+
371+
for (ix = 0; ix < RXRPC_RXTX_BUFF_SIZE; ix++) {
372+
skb = call->rxtx_buffer[ix];
373+
if (!skb)
374+
continue;
375+
376+
sp = rxrpc_skb(skb);
377+
if (sp->hdr.serial != orig_serial)
378+
continue;
379+
smp_rmb();
380+
sent_at = skb->tstamp;
381+
goto found;
382+
}
383+
return;
384+
385+
found:
386+
rxrpc_peer_add_rtt(call, rxrpc_rtt_rx_requested_ack,
387+
orig_serial, ack_serial, sent_at, resp_time);
388+
}
389+
358390
/*
359391
* Process a ping response.
360392
*/
@@ -508,6 +540,9 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
508540
if (buf.ack.reason == RXRPC_ACK_PING_RESPONSE)
509541
rxrpc_input_ping_response(call, skb->tstamp, acked_serial,
510542
sp->hdr.serial);
543+
if (buf.ack.reason == RXRPC_ACK_REQUESTED)
544+
rxrpc_input_requested_ack(call, skb->tstamp, acked_serial,
545+
sp->hdr.serial);
511546

512547
if (buf.ack.reason == RXRPC_ACK_PING) {
513548
_proto("Rx ACK %%%u PING Request", sp->hdr.serial);

net/rxrpc/misc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ unsigned int rxrpc_rx_mtu = 5692;
6868
unsigned int rxrpc_rx_jumbo_max = 4;
6969

7070
/*
71-
* Time till packet resend (in jiffies).
71+
* Time till packet resend (in milliseconds).
7272
*/
73-
unsigned int rxrpc_resend_timeout = 4 * HZ;
73+
unsigned int rxrpc_resend_timeout = 4 * 1000;
7474

7575
const char *const rxrpc_pkts[] = {
7676
"?00",
@@ -186,8 +186,10 @@ const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5] = {
186186

187187
const char rxrpc_rtt_tx_traces[rxrpc_rtt_tx__nr_trace][5] = {
188188
[rxrpc_rtt_tx_ping] = "PING",
189+
[rxrpc_rtt_tx_data] = "DATA",
189190
};
190191

191192
const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5] = {
192193
[rxrpc_rtt_rx_ping_response] = "PONG",
194+
[rxrpc_rtt_rx_requested_ack] = "RACK",
193195
};

net/rxrpc/output.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,12 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb)
300300
goto send_fragmentable;
301301

302302
done:
303-
if (ret == 0) {
304-
sp->resend_at = jiffies + rxrpc_resend_timeout;
303+
if (ret >= 0) {
304+
skb->tstamp = ktime_get_real();
305+
smp_wmb();
305306
sp->hdr.serial = serial;
307+
if (whdr.flags & RXRPC_REQUEST_ACK)
308+
trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_data, serial);
306309
}
307310
_leave(" = %d [%u]", ret, call->peer->maxdata);
308311
return ret;

net/rxrpc/sendmsg.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb,
137137
if (seq == 1 && rxrpc_is_client_call(call))
138138
rxrpc_expose_client_call(call);
139139

140-
sp->resend_at = jiffies + rxrpc_resend_timeout;
141140
ret = rxrpc_send_data_packet(call, skb);
142141
if (ret < 0) {
143142
_debug("need instant resend %d", ret);

net/rxrpc/sysctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static struct ctl_table rxrpc_sysctl_table[] = {
5959
.data = &rxrpc_resend_timeout,
6060
.maxlen = sizeof(unsigned int),
6161
.mode = 0644,
62-
.proc_handler = proc_dointvec_ms_jiffies,
62+
.proc_handler = proc_dointvec,
6363
.extra1 = (void *)&one,
6464
},
6565
{

0 commit comments

Comments
 (0)