aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-09-21 19:29:31 -0400
committerDavid Howells <dhowells@redhat.com>2016-09-22 03:21:24 -0400
commit50235c4b5a2fb9a9690f02cd1dea6ca047d7f79e (patch)
tree3dc5a178820b16d5eaef0484fe7751cb4f71375e
parent77f2efcbdd7133466060198e02c6e8a170c3cd14 (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.h7
-rw-r--r--net/rxrpc/call_event.c19
-rw-r--r--net/rxrpc/input.c35
-rw-r--r--net/rxrpc/misc.c6
-rw-r--r--net/rxrpc/output.c7
-rw-r--r--net/rxrpc/sendmsg.c1
-rw-r--r--net/rxrpc/sysctl.c2
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 */
143struct rxrpc_skb_priv { 143struct 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
664enum rxrpc_rtt_tx_trace { 661enum 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
671enum rxrpc_rtt_rx_trace { 669enum 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 */
361static 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
385found:
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 */
361static void rxrpc_input_ping_response(struct rxrpc_call *call, 393static 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;
68unsigned int rxrpc_rx_jumbo_max = 4; 68unsigned 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 */
73unsigned int rxrpc_resend_timeout = 4 * HZ; 73unsigned int rxrpc_resend_timeout = 4 * 1000;
74 74
75const char *const rxrpc_pkts[] = { 75const char *const rxrpc_pkts[] = {
76 "?00", 76 "?00",
@@ -186,8 +186,10 @@ const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5] = {
186 186
187const char rxrpc_rtt_tx_traces[rxrpc_rtt_tx__nr_trace][5] = { 187const 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
191const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5] = { 192const 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
302done: 302done:
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 {