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:
David Howells
2017-11-24 10:18:42 +00:00
parent bd1fdf8cfd
commit 415f44e432
4 changed files with 40 additions and 0 deletions

View File

@@ -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;