rxrpc: Add keepalive for a call
We need to transmit a packet every so often to act as a keepalive for the peer (which has a timeout from the last time it received a packet) and also to prevent any intervening firewalls from closing the route. Do this by resetting a timer every time we transmit a packet. If the timer ever expires, we transmit a PING ACK packet and thereby also elicit a PING RESPONSE ACK from the other side - which prevents our last-rx timeout from expiring. The timer is set to 1/6 of the last-rx timeout so that we can detect the other side going away if it misses 6 replies in a row. This is particularly necessary for servers where the processing of the service function may take a significant amount of time. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
parent
bd1fdf8cfd
commit
415f44e432
|
@ -141,6 +141,7 @@ enum rxrpc_timer_trace {
|
|||
rxrpc_timer_exp_ack,
|
||||
rxrpc_timer_exp_hard,
|
||||
rxrpc_timer_exp_idle,
|
||||
rxrpc_timer_exp_keepalive,
|
||||
rxrpc_timer_exp_lost_ack,
|
||||
rxrpc_timer_exp_normal,
|
||||
rxrpc_timer_exp_ping,
|
||||
|
@ -152,6 +153,7 @@ enum rxrpc_timer_trace {
|
|||
rxrpc_timer_set_for_ack,
|
||||
rxrpc_timer_set_for_hard,
|
||||
rxrpc_timer_set_for_idle,
|
||||
rxrpc_timer_set_for_keepalive,
|
||||
rxrpc_timer_set_for_lost_ack,
|
||||
rxrpc_timer_set_for_normal,
|
||||
rxrpc_timer_set_for_ping,
|
||||
|
@ -162,6 +164,7 @@ enum rxrpc_timer_trace {
|
|||
enum rxrpc_propose_ack_trace {
|
||||
rxrpc_propose_ack_client_tx_end,
|
||||
rxrpc_propose_ack_input_data,
|
||||
rxrpc_propose_ack_ping_for_keepalive,
|
||||
rxrpc_propose_ack_ping_for_lost_ack,
|
||||
rxrpc_propose_ack_ping_for_lost_reply,
|
||||
rxrpc_propose_ack_ping_for_params,
|
||||
|
@ -311,6 +314,7 @@ enum rxrpc_congest_change {
|
|||
EM(rxrpc_timer_exp_ack, "ExpAck") \
|
||||
EM(rxrpc_timer_exp_hard, "ExpHrd") \
|
||||
EM(rxrpc_timer_exp_idle, "ExpIdl") \
|
||||
EM(rxrpc_timer_exp_keepalive, "ExpKA ") \
|
||||
EM(rxrpc_timer_exp_lost_ack, "ExpLoA") \
|
||||
EM(rxrpc_timer_exp_normal, "ExpNml") \
|
||||
EM(rxrpc_timer_exp_ping, "ExpPng") \
|
||||
|
@ -321,6 +325,7 @@ enum rxrpc_congest_change {
|
|||
EM(rxrpc_timer_set_for_ack, "SetAck") \
|
||||
EM(rxrpc_timer_set_for_hard, "SetHrd") \
|
||||
EM(rxrpc_timer_set_for_idle, "SetIdl") \
|
||||
EM(rxrpc_timer_set_for_keepalive, "KeepAl") \
|
||||
EM(rxrpc_timer_set_for_lost_ack, "SetLoA") \
|
||||
EM(rxrpc_timer_set_for_normal, "SetNml") \
|
||||
EM(rxrpc_timer_set_for_ping, "SetPng") \
|
||||
|
@ -330,6 +335,7 @@ enum rxrpc_congest_change {
|
|||
#define rxrpc_propose_ack_traces \
|
||||
EM(rxrpc_propose_ack_client_tx_end, "ClTxEnd") \
|
||||
EM(rxrpc_propose_ack_input_data, "DataIn ") \
|
||||
EM(rxrpc_propose_ack_ping_for_keepalive, "KeepAlv") \
|
||||
EM(rxrpc_propose_ack_ping_for_lost_ack, "LostAck") \
|
||||
EM(rxrpc_propose_ack_ping_for_lost_reply, "LostRpl") \
|
||||
EM(rxrpc_propose_ack_ping_for_params, "Params ") \
|
||||
|
|
|
@ -519,6 +519,7 @@ struct rxrpc_call {
|
|||
unsigned long ack_lost_at; /* When ACK is figured as lost */
|
||||
unsigned long resend_at; /* When next resend needs to happen */
|
||||
unsigned long ping_at; /* When next to send a ping */
|
||||
unsigned long keepalive_at; /* When next to send a keepalive ping */
|
||||
unsigned long expect_rx_by; /* When we expect to get a packet by */
|
||||
unsigned long expect_req_by; /* When we expect to get a request DATA packet by */
|
||||
unsigned long expect_term_by; /* When we expect call termination by */
|
||||
|
|
|
@ -366,6 +366,15 @@ recheck_state:
|
|||
set_bit(RXRPC_CALL_EV_ACK_LOST, &call->events);
|
||||
}
|
||||
|
||||
t = READ_ONCE(call->keepalive_at);
|
||||
if (time_after_eq(now, t)) {
|
||||
trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now);
|
||||
cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET);
|
||||
rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, true,
|
||||
rxrpc_propose_ack_ping_for_keepalive);
|
||||
set_bit(RXRPC_CALL_EV_PING, &call->events);
|
||||
}
|
||||
|
||||
t = READ_ONCE(call->ping_at);
|
||||
if (time_after_eq(now, t)) {
|
||||
trace_rxrpc_timer(call, rxrpc_timer_exp_ping, now);
|
||||
|
@ -423,6 +432,7 @@ recheck_state:
|
|||
set(call->ack_at);
|
||||
set(call->ack_lost_at);
|
||||
set(call->resend_at);
|
||||
set(call->keepalive_at);
|
||||
set(call->ping_at);
|
||||
|
||||
now = jiffies;
|
||||
|
|
|
@ -32,6 +32,24 @@ struct rxrpc_abort_buffer {
|
|||
__be32 abort_code;
|
||||
};
|
||||
|
||||
/*
|
||||
* Arrange for a keepalive ping a certain time after we last transmitted. This
|
||||
* lets the far side know we're still interested in this call and helps keep
|
||||
* the route through any intervening firewall open.
|
||||
*
|
||||
* Receiving a response to the ping will prevent the ->expect_rx_by timer from
|
||||
* expiring.
|
||||
*/
|
||||
static void rxrpc_set_keepalive(struct rxrpc_call *call)
|
||||
{
|
||||
unsigned long now = jiffies, keepalive_at = call->next_rx_timo / 6;
|
||||
|
||||
keepalive_at += now;
|
||||
WRITE_ONCE(call->keepalive_at, keepalive_at);
|
||||
rxrpc_reduce_call_timer(call, keepalive_at, now,
|
||||
rxrpc_timer_set_for_keepalive);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill out an ACK packet.
|
||||
*/
|
||||
|
@ -205,6 +223,8 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
|
|||
call->ackr_seen = top;
|
||||
spin_unlock_bh(&call->lock);
|
||||
}
|
||||
|
||||
rxrpc_set_keepalive(call);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -388,6 +408,9 @@ done:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
rxrpc_set_keepalive(call);
|
||||
|
||||
_leave(" = %d [%u]", ret, call->peer->maxdata);
|
||||
return ret;
|
||||
|
||||
|
|
Loading…
Reference in New Issue