rxrpc: Schedule an ACK if the reply to a client call appears overdue
authorDavid Howells <dhowells@redhat.com>
Sat, 24 Sep 2016 17:05:27 +0000 (18:05 +0100)
committerDavid Howells <dhowells@redhat.com>
Sat, 24 Sep 2016 22:49:46 +0000 (23:49 +0100)
If we've sent all the request data in a client call but haven't seen any
sign of the reply data yet, schedule an ACK to be sent to the server to
find out if the reply data got lost.

If the server hasn't yet hard-ACK'd the request data, we send a PING ACK to
demand a response to find out whether we need to retransmit.

If the server says it has received all of the data, we send an IDLE ACK to
tell the server that we haven't received anything in the receive phase as
yet.

To make this work, a non-immediate PING ACK must carry a delay.  I've chosen
the same as the IDLE ACK for the moment.

Signed-off-by: David Howells <dhowells@redhat.com>
net/rxrpc/ar-internal.h
net/rxrpc/call_event.c
net/rxrpc/input.c
net/rxrpc/misc.c

index 1a700b6a998bf48d4981d96e15b6eb4b81aa4873..b1e697fc9ffbb15ffd8b10f8ef9905e395d372dc 100644 (file)
@@ -707,7 +707,9 @@ enum rxrpc_timer_trace {
 extern const char rxrpc_timer_traces[rxrpc_timer__nr_trace][8];
 
 enum rxrpc_propose_ack_trace {
+       rxrpc_propose_ack_client_tx_end,
        rxrpc_propose_ack_input_data,
+       rxrpc_propose_ack_ping_for_lost_reply,
        rxrpc_propose_ack_ping_for_params,
        rxrpc_propose_ack_respond_to_ack,
        rxrpc_propose_ack_respond_to_ping,
index d5bf9ce7ec6f56c8b4991582c1eac7e4cf812491..05b94d1acf527c14800bc6242d58484d0160ea55 100644 (file)
@@ -100,6 +100,7 @@ static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
                        expiry = rxrpc_soft_ack_delay;
                break;
 
+       case RXRPC_ACK_PING:
        case RXRPC_ACK_IDLE:
                if (rxrpc_idle_ack_delay < expiry)
                        expiry = rxrpc_idle_ack_delay;
index dd699667eeefcb59e000cd656eb8dbde2f8243de..0344f4494eb739c99959cd2449817090db801b61 100644 (file)
@@ -138,6 +138,8 @@ static bool rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
 
        write_unlock(&call->state_lock);
        if (call->state == RXRPC_CALL_CLIENT_AWAIT_REPLY) {
+               rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, 0, false, true,
+                                 rxrpc_propose_ack_client_tx_end);
                trace_rxrpc_transmit(call, rxrpc_transmit_await_reply);
        } else {
                trace_rxrpc_transmit(call, rxrpc_transmit_end);
@@ -684,6 +686,12 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
                return;
        }
 
+       if (call->rxtx_annotations[call->tx_top & RXRPC_RXTX_BUFF_MASK] &
+           RXRPC_TX_ANNO_LAST &&
+           summary.nr_acks == call->tx_top - hard_ack)
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+                                 false, true,
+                                 rxrpc_propose_ack_ping_for_lost_reply);
 }
 
 /*
index 901c012a2700f7b6160223f904d691fb8882ebbb..a608769343e6402747e8a674e17845b573bcf675 100644 (file)
@@ -198,7 +198,9 @@ const char rxrpc_timer_traces[rxrpc_timer__nr_trace][8] = {
 };
 
 const char rxrpc_propose_ack_traces[rxrpc_propose_ack__nr_trace][8] = {
+       [rxrpc_propose_ack_client_tx_end]       = "ClTxEnd",
        [rxrpc_propose_ack_input_data]          = "DataIn ",
+       [rxrpc_propose_ack_ping_for_lost_reply] = "LostRpl",
        [rxrpc_propose_ack_ping_for_params]     = "Params ",
        [rxrpc_propose_ack_respond_to_ack]      = "Rsp2Ack",
        [rxrpc_propose_ack_respond_to_ping]     = "Rsp2Png",