diff options
author | David Howells <dhowells@redhat.com> | 2016-09-21 19:29:31 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2016-09-22 03:21:24 -0400 |
commit | 50235c4b5a2fb9a9690f02cd1dea6ca047d7f79e (patch) | |
tree | 3dc5a178820b16d5eaef0484fe7751cb4f71375e | |
parent | 77f2efcbdd7133466060198e02c6e8a170c3cd14 (diff) |
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 <dhowells@redhat.com>
-rw-r--r-- | net/rxrpc/ar-internal.h | 7 | ||||
-rw-r--r-- | net/rxrpc/call_event.c | 19 | ||||
-rw-r--r-- | net/rxrpc/input.c | 35 | ||||
-rw-r--r-- | net/rxrpc/misc.c | 6 | ||||
-rw-r--r-- | net/rxrpc/output.c | 7 | ||||
-rw-r--r-- | net/rxrpc/sendmsg.c | 1 | ||||
-rw-r--r-- | net/rxrpc/sysctl.c | 2 |
7 files changed, 57 insertions, 20 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 8b47f468eb9d..1c4597b2c6cd 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
@@ -142,10 +142,7 @@ struct rxrpc_host_header { | |||
142 | */ | 142 | */ |
143 | struct rxrpc_skb_priv { | 143 | struct rxrpc_skb_priv { |
144 | union { | 144 | union { |
145 | unsigned long resend_at; /* time in jiffies at which to resend */ | 145 | u8 nr_jumbo; /* Number of jumbo subpackets */ |
146 | struct { | ||
147 | u8 nr_jumbo; /* Number of jumbo subpackets */ | ||
148 | }; | ||
149 | }; | 146 | }; |
150 | union { | 147 | union { |
151 | unsigned int offset; /* offset into buffer of next read */ | 148 | unsigned int offset; /* offset into buffer of next read */ |
@@ -663,6 +660,7 @@ extern const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5]; | |||
663 | 660 | ||
664 | enum rxrpc_rtt_tx_trace { | 661 | enum rxrpc_rtt_tx_trace { |
665 | rxrpc_rtt_tx_ping, | 662 | rxrpc_rtt_tx_ping, |
663 | rxrpc_rtt_tx_data, | ||
666 | rxrpc_rtt_tx__nr_trace | 664 | rxrpc_rtt_tx__nr_trace |
667 | }; | 665 | }; |
668 | 666 | ||
@@ -670,6 +668,7 @@ extern const char rxrpc_rtt_tx_traces[rxrpc_rtt_tx__nr_trace][5]; | |||
670 | 668 | ||
671 | enum rxrpc_rtt_rx_trace { | 669 | enum rxrpc_rtt_rx_trace { |
672 | rxrpc_rtt_rx_ping_response, | 670 | rxrpc_rtt_rx_ping_response, |
671 | rxrpc_rtt_rx_requested_ack, | ||
673 | rxrpc_rtt_rx__nr_trace | 672 | rxrpc_rtt_rx__nr_trace |
674 | }; | 673 | }; |
675 | 674 | ||
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c index 34ad967f2d81..adb2ec61e21f 100644 --- a/net/rxrpc/call_event.c +++ b/net/rxrpc/call_event.c | |||
@@ -142,12 +142,14 @@ static void rxrpc_resend(struct rxrpc_call *call) | |||
142 | struct rxrpc_skb_priv *sp; | 142 | struct rxrpc_skb_priv *sp; |
143 | struct sk_buff *skb; | 143 | struct sk_buff *skb; |
144 | rxrpc_seq_t cursor, seq, top; | 144 | rxrpc_seq_t cursor, seq, top; |
145 | unsigned long resend_at, now; | 145 | ktime_t now = ktime_get_real(), max_age, oldest, resend_at; |
146 | int ix; | 146 | int ix; |
147 | u8 annotation, anno_type; | 147 | u8 annotation, anno_type; |
148 | 148 | ||
149 | _enter("{%d,%d}", call->tx_hard_ack, call->tx_top); | 149 | _enter("{%d,%d}", call->tx_hard_ack, call->tx_top); |
150 | 150 | ||
151 | max_age = ktime_sub_ms(now, rxrpc_resend_timeout); | ||
152 | |||
151 | spin_lock_bh(&call->lock); | 153 | spin_lock_bh(&call->lock); |
152 | 154 | ||
153 | cursor = call->tx_hard_ack; | 155 | cursor = call->tx_hard_ack; |
@@ -160,8 +162,7 @@ static void rxrpc_resend(struct rxrpc_call *call) | |||
160 | * the packets in the Tx buffer we're going to resend and what the new | 162 | * the packets in the Tx buffer we're going to resend and what the new |
161 | * resend timeout will be. | 163 | * resend timeout will be. |
162 | */ | 164 | */ |
163 | now = jiffies; | 165 | oldest = now; |
164 | resend_at = now + rxrpc_resend_timeout; | ||
165 | for (seq = cursor + 1; before_eq(seq, top); seq++) { | 166 | for (seq = cursor + 1; before_eq(seq, top); seq++) { |
166 | ix = seq & RXRPC_RXTX_BUFF_MASK; | 167 | ix = seq & RXRPC_RXTX_BUFF_MASK; |
167 | annotation = call->rxtx_annotations[ix]; | 168 | annotation = call->rxtx_annotations[ix]; |
@@ -175,9 +176,9 @@ static void rxrpc_resend(struct rxrpc_call *call) | |||
175 | sp = rxrpc_skb(skb); | 176 | sp = rxrpc_skb(skb); |
176 | 177 | ||
177 | if (anno_type == RXRPC_TX_ANNO_UNACK) { | 178 | if (anno_type == RXRPC_TX_ANNO_UNACK) { |
178 | if (time_after(sp->resend_at, now)) { | 179 | if (ktime_after(skb->tstamp, max_age)) { |
179 | if (time_before(sp->resend_at, resend_at)) | 180 | if (ktime_before(skb->tstamp, oldest)) |
180 | resend_at = sp->resend_at; | 181 | oldest = skb->tstamp; |
181 | continue; | 182 | continue; |
182 | } | 183 | } |
183 | } | 184 | } |
@@ -186,7 +187,8 @@ static void rxrpc_resend(struct rxrpc_call *call) | |||
186 | call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation; | 187 | call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation; |
187 | } | 188 | } |
188 | 189 | ||
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)); | ||
190 | 192 | ||
191 | /* Now go through the Tx window and perform the retransmissions. We | 193 | /* Now go through the Tx window and perform the retransmissions. We |
192 | * have to drop the lock for each send. If an ACK comes in whilst the | 194 | * 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) | |||
205 | spin_unlock_bh(&call->lock); | 207 | spin_unlock_bh(&call->lock); |
206 | 208 | ||
207 | if (rxrpc_send_data_packet(call, skb) < 0) { | 209 | if (rxrpc_send_data_packet(call, skb) < 0) { |
208 | call->resend_at = now + 2; | ||
209 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); | 210 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
210 | return; | 211 | return; |
211 | } | 212 | } |
212 | 213 | ||
213 | if (rxrpc_is_client_call(call)) | 214 | if (rxrpc_is_client_call(call)) |
214 | rxrpc_expose_client_call(call); | 215 | rxrpc_expose_client_call(call); |
215 | sp = rxrpc_skb(skb); | ||
216 | sp->resend_at = now + rxrpc_resend_timeout; | ||
217 | 216 | ||
218 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); | 217 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
219 | spin_lock_bh(&call->lock); | 218 | spin_lock_bh(&call->lock); |
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index a0a5bd108c9e..c121949de3c8 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c | |||
@@ -356,6 +356,38 @@ ack: | |||
356 | } | 356 | } |
357 | 357 | ||
358 | /* | 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 | |||
390 | /* | ||
359 | * Process a ping response. | 391 | * Process a ping response. |
360 | */ | 392 | */ |
361 | static void rxrpc_input_ping_response(struct rxrpc_call *call, | 393 | static void rxrpc_input_ping_response(struct rxrpc_call *call, |
@@ -508,6 +540,9 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb, | |||
508 | if (buf.ack.reason == RXRPC_ACK_PING_RESPONSE) | 540 | if (buf.ack.reason == RXRPC_ACK_PING_RESPONSE) |
509 | rxrpc_input_ping_response(call, skb->tstamp, acked_serial, | 541 | rxrpc_input_ping_response(call, skb->tstamp, acked_serial, |
510 | sp->hdr.serial); | 542 | 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); | ||
511 | 546 | ||
512 | if (buf.ack.reason == RXRPC_ACK_PING) { | 547 | if (buf.ack.reason == RXRPC_ACK_PING) { |
513 | _proto("Rx ACK %%%u PING Request", sp->hdr.serial); | 548 | _proto("Rx ACK %%%u PING Request", sp->hdr.serial); |
diff --git a/net/rxrpc/misc.c b/net/rxrpc/misc.c index 56e668352fc7..0d425e707f22 100644 --- a/net/rxrpc/misc.c +++ b/net/rxrpc/misc.c | |||
@@ -68,9 +68,9 @@ unsigned int rxrpc_rx_mtu = 5692; | |||
68 | unsigned int rxrpc_rx_jumbo_max = 4; | 68 | unsigned int rxrpc_rx_jumbo_max = 4; |
69 | 69 | ||
70 | /* | 70 | /* |
71 | * Time till packet resend (in jiffies). | 71 | * Time till packet resend (in milliseconds). |
72 | */ | 72 | */ |
73 | unsigned int rxrpc_resend_timeout = 4 * HZ; | 73 | unsigned int rxrpc_resend_timeout = 4 * 1000; |
74 | 74 | ||
75 | const char *const rxrpc_pkts[] = { | 75 | const char *const rxrpc_pkts[] = { |
76 | "?00", | 76 | "?00", |
@@ -186,8 +186,10 @@ const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5] = { | |||
186 | 186 | ||
187 | const char rxrpc_rtt_tx_traces[rxrpc_rtt_tx__nr_trace][5] = { | 187 | const char rxrpc_rtt_tx_traces[rxrpc_rtt_tx__nr_trace][5] = { |
188 | [rxrpc_rtt_tx_ping] = "PING", | 188 | [rxrpc_rtt_tx_ping] = "PING", |
189 | [rxrpc_rtt_tx_data] = "DATA", | ||
189 | }; | 190 | }; |
190 | 191 | ||
191 | const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5] = { | 192 | const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5] = { |
192 | [rxrpc_rtt_rx_ping_response] = "PONG", | 193 | [rxrpc_rtt_rx_ping_response] = "PONG", |
194 | [rxrpc_rtt_rx_requested_ack] = "RACK", | ||
193 | }; | 195 | }; |
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c index 0d89cd3f2c01..db01fbb70d23 100644 --- a/net/rxrpc/output.c +++ b/net/rxrpc/output.c | |||
@@ -300,9 +300,12 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb) | |||
300 | goto send_fragmentable; | 300 | goto send_fragmentable; |
301 | 301 | ||
302 | done: | 302 | done: |
303 | if (ret == 0) { | 303 | if (ret >= 0) { |
304 | sp->resend_at = jiffies + rxrpc_resend_timeout; | 304 | skb->tstamp = ktime_get_real(); |
305 | smp_wmb(); | ||
305 | sp->hdr.serial = serial; | 306 | sp->hdr.serial = serial; |
307 | if (whdr.flags & RXRPC_REQUEST_ACK) | ||
308 | trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_data, serial); | ||
306 | } | 309 | } |
307 | _leave(" = %d [%u]", ret, call->peer->maxdata); | 310 | _leave(" = %d [%u]", ret, call->peer->maxdata); |
308 | return ret; | 311 | return ret; |
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 3c969de3ef05..607223f4f871 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c | |||
@@ -137,7 +137,6 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb, | |||
137 | if (seq == 1 && rxrpc_is_client_call(call)) | 137 | if (seq == 1 && rxrpc_is_client_call(call)) |
138 | rxrpc_expose_client_call(call); | 138 | rxrpc_expose_client_call(call); |
139 | 139 | ||
140 | sp->resend_at = jiffies + rxrpc_resend_timeout; | ||
141 | ret = rxrpc_send_data_packet(call, skb); | 140 | ret = rxrpc_send_data_packet(call, skb); |
142 | if (ret < 0) { | 141 | if (ret < 0) { |
143 | _debug("need instant resend %d", ret); | 142 | _debug("need instant resend %d", ret); |
diff --git a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c index a03c61c672f5..13d1df03ebac 100644 --- a/net/rxrpc/sysctl.c +++ b/net/rxrpc/sysctl.c | |||
@@ -59,7 +59,7 @@ static struct ctl_table rxrpc_sysctl_table[] = { | |||
59 | .data = &rxrpc_resend_timeout, | 59 | .data = &rxrpc_resend_timeout, |
60 | .maxlen = sizeof(unsigned int), | 60 | .maxlen = sizeof(unsigned int), |
61 | .mode = 0644, | 61 | .mode = 0644, |
62 | .proc_handler = proc_dointvec_ms_jiffies, | 62 | .proc_handler = proc_dointvec, |
63 | .extra1 = (void *)&one, | 63 | .extra1 = (void *)&one, |
64 | }, | 64 | }, |
65 | { | 65 | { |