aboutsummaryrefslogtreecommitdiffstats
path: root/net/rxrpc/input.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2017-11-24 05:18:42 -0500
committerDavid Howells <dhowells@redhat.com>2017-11-24 05:18:42 -0500
commitbd1fdf8cfdf3fdbccd2b21c33ec649ebd7429af7 (patch)
treea4bd170409584ba9950b3193cd11213fb2552694 /net/rxrpc/input.c
parentbeb8e5e4f38cc3e4c2839cfc143e0312bf53d0e0 (diff)
rxrpc: Add a timeout for detecting lost ACKs/lost DATA
Add an extra timeout that is set/updated when we send a DATA packet that has the request-ack flag set. This allows us to detect if we don't get an ACK in response to the latest flagged packet. The ACK packet is adjudged to have been lost if it doesn't turn up within 2*RTT of the transmission. If the timeout occurs, we schedule the sending of a PING ACK to find out the state of the other side. If a new DATA packet is ready to go sooner, we cancel the sending of the ping and set the request-ack flag on that instead. If we get back a PING-RESPONSE ACK that indicates a lower tx_top than what we had at the time of the ping transmission, we adjudge all the DATA packets sent between the response tx_top and the ping-time tx_top to have been lost and retransmit immediately. Rather than sending a PING ACK, we could just pick a DATA packet and speculatively retransmit that with request-ack set. It should result in either a REQUESTED ACK or a DUPLICATE ACK which we can then use in lieu the a PING-RESPONSE ACK mentioned above. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc/input.c')
-rw-r--r--net/rxrpc/input.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index c89647eae86d..23a5e61d8f79 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -631,6 +631,43 @@ found:
631} 631}
632 632
633/* 633/*
634 * Process the response to a ping that we sent to find out if we lost an ACK.
635 *
636 * If we got back a ping response that indicates a lower tx_top than what we
637 * had at the time of the ping transmission, we adjudge all the DATA packets
638 * sent between the response tx_top and the ping-time tx_top to have been lost.
639 */
640static void rxrpc_input_check_for_lost_ack(struct rxrpc_call *call)
641{
642 rxrpc_seq_t top, bottom, seq;
643 bool resend = false;
644
645 spin_lock_bh(&call->lock);
646
647 bottom = call->tx_hard_ack + 1;
648 top = call->acks_lost_top;
649 if (before(bottom, top)) {
650 for (seq = bottom; before_eq(seq, top); seq++) {
651 int ix = seq & RXRPC_RXTX_BUFF_MASK;
652 u8 annotation = call->rxtx_annotations[ix];
653 u8 anno_type = annotation & RXRPC_TX_ANNO_MASK;
654
655 if (anno_type != RXRPC_TX_ANNO_UNACK)
656 continue;
657 annotation &= ~RXRPC_TX_ANNO_MASK;
658 annotation |= RXRPC_TX_ANNO_RETRANS;
659 call->rxtx_annotations[ix] = annotation;
660 resend = true;
661 }
662 }
663
664 spin_unlock_bh(&call->lock);
665
666 if (resend && !test_and_set_bit(RXRPC_CALL_EV_RESEND, &call->events))
667 rxrpc_queue_call(call);
668}
669
670/*
634 * Process a ping response. 671 * Process a ping response.
635 */ 672 */
636static void rxrpc_input_ping_response(struct rxrpc_call *call, 673static void rxrpc_input_ping_response(struct rxrpc_call *call,
@@ -645,6 +682,9 @@ static void rxrpc_input_ping_response(struct rxrpc_call *call,
645 smp_rmb(); 682 smp_rmb();
646 ping_serial = call->ping_serial; 683 ping_serial = call->ping_serial;
647 684
685 if (orig_serial == call->acks_lost_ping)
686 rxrpc_input_check_for_lost_ack(call);
687
648 if (!test_bit(RXRPC_CALL_PINGING, &call->flags) || 688 if (!test_bit(RXRPC_CALL_PINGING, &call->flags) ||
649 before(orig_serial, ping_serial)) 689 before(orig_serial, ping_serial))
650 return; 690 return;