Skip to content

Commit 415f44e

Browse files
committed
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 <[email protected]>
1 parent bd1fdf8 commit 415f44e

File tree

4 files changed

+40
-0
lines changed

4 files changed

+40
-0
lines changed

include/trace/events/rxrpc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ enum rxrpc_timer_trace {
141141
rxrpc_timer_exp_ack,
142142
rxrpc_timer_exp_hard,
143143
rxrpc_timer_exp_idle,
144+
rxrpc_timer_exp_keepalive,
144145
rxrpc_timer_exp_lost_ack,
145146
rxrpc_timer_exp_normal,
146147
rxrpc_timer_exp_ping,
@@ -152,6 +153,7 @@ enum rxrpc_timer_trace {
152153
rxrpc_timer_set_for_ack,
153154
rxrpc_timer_set_for_hard,
154155
rxrpc_timer_set_for_idle,
156+
rxrpc_timer_set_for_keepalive,
155157
rxrpc_timer_set_for_lost_ack,
156158
rxrpc_timer_set_for_normal,
157159
rxrpc_timer_set_for_ping,
@@ -162,6 +164,7 @@ enum rxrpc_timer_trace {
162164
enum rxrpc_propose_ack_trace {
163165
rxrpc_propose_ack_client_tx_end,
164166
rxrpc_propose_ack_input_data,
167+
rxrpc_propose_ack_ping_for_keepalive,
165168
rxrpc_propose_ack_ping_for_lost_ack,
166169
rxrpc_propose_ack_ping_for_lost_reply,
167170
rxrpc_propose_ack_ping_for_params,
@@ -311,6 +314,7 @@ enum rxrpc_congest_change {
311314
EM(rxrpc_timer_exp_ack, "ExpAck") \
312315
EM(rxrpc_timer_exp_hard, "ExpHrd") \
313316
EM(rxrpc_timer_exp_idle, "ExpIdl") \
317+
EM(rxrpc_timer_exp_keepalive, "ExpKA ") \
314318
EM(rxrpc_timer_exp_lost_ack, "ExpLoA") \
315319
EM(rxrpc_timer_exp_normal, "ExpNml") \
316320
EM(rxrpc_timer_exp_ping, "ExpPng") \
@@ -321,6 +325,7 @@ enum rxrpc_congest_change {
321325
EM(rxrpc_timer_set_for_ack, "SetAck") \
322326
EM(rxrpc_timer_set_for_hard, "SetHrd") \
323327
EM(rxrpc_timer_set_for_idle, "SetIdl") \
328+
EM(rxrpc_timer_set_for_keepalive, "KeepAl") \
324329
EM(rxrpc_timer_set_for_lost_ack, "SetLoA") \
325330
EM(rxrpc_timer_set_for_normal, "SetNml") \
326331
EM(rxrpc_timer_set_for_ping, "SetPng") \
@@ -330,6 +335,7 @@ enum rxrpc_congest_change {
330335
#define rxrpc_propose_ack_traces \
331336
EM(rxrpc_propose_ack_client_tx_end, "ClTxEnd") \
332337
EM(rxrpc_propose_ack_input_data, "DataIn ") \
338+
EM(rxrpc_propose_ack_ping_for_keepalive, "KeepAlv") \
333339
EM(rxrpc_propose_ack_ping_for_lost_ack, "LostAck") \
334340
EM(rxrpc_propose_ack_ping_for_lost_reply, "LostRpl") \
335341
EM(rxrpc_propose_ack_ping_for_params, "Params ") \

net/rxrpc/ar-internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ struct rxrpc_call {
519519
unsigned long ack_lost_at; /* When ACK is figured as lost */
520520
unsigned long resend_at; /* When next resend needs to happen */
521521
unsigned long ping_at; /* When next to send a ping */
522+
unsigned long keepalive_at; /* When next to send a keepalive ping */
522523
unsigned long expect_rx_by; /* When we expect to get a packet by */
523524
unsigned long expect_req_by; /* When we expect to get a request DATA packet by */
524525
unsigned long expect_term_by; /* When we expect call termination by */

net/rxrpc/call_event.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,15 @@ void rxrpc_process_call(struct work_struct *work)
366366
set_bit(RXRPC_CALL_EV_ACK_LOST, &call->events);
367367
}
368368

369+
t = READ_ONCE(call->keepalive_at);
370+
if (time_after_eq(now, t)) {
371+
trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now);
372+
cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET);
373+
rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, true,
374+
rxrpc_propose_ack_ping_for_keepalive);
375+
set_bit(RXRPC_CALL_EV_PING, &call->events);
376+
}
377+
369378
t = READ_ONCE(call->ping_at);
370379
if (time_after_eq(now, t)) {
371380
trace_rxrpc_timer(call, rxrpc_timer_exp_ping, now);
@@ -423,6 +432,7 @@ void rxrpc_process_call(struct work_struct *work)
423432
set(call->ack_at);
424433
set(call->ack_lost_at);
425434
set(call->resend_at);
435+
set(call->keepalive_at);
426436
set(call->ping_at);
427437

428438
now = jiffies;

net/rxrpc/output.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,24 @@ struct rxrpc_abort_buffer {
3232
__be32 abort_code;
3333
};
3434

35+
/*
36+
* Arrange for a keepalive ping a certain time after we last transmitted. This
37+
* lets the far side know we're still interested in this call and helps keep
38+
* the route through any intervening firewall open.
39+
*
40+
* Receiving a response to the ping will prevent the ->expect_rx_by timer from
41+
* expiring.
42+
*/
43+
static void rxrpc_set_keepalive(struct rxrpc_call *call)
44+
{
45+
unsigned long now = jiffies, keepalive_at = call->next_rx_timo / 6;
46+
47+
keepalive_at += now;
48+
WRITE_ONCE(call->keepalive_at, keepalive_at);
49+
rxrpc_reduce_call_timer(call, keepalive_at, now,
50+
rxrpc_timer_set_for_keepalive);
51+
}
52+
3553
/*
3654
* Fill out an ACK packet.
3755
*/
@@ -205,6 +223,8 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
205223
call->ackr_seen = top;
206224
spin_unlock_bh(&call->lock);
207225
}
226+
227+
rxrpc_set_keepalive(call);
208228
}
209229

210230
out:
@@ -388,6 +408,9 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
388408
}
389409
}
390410
}
411+
412+
rxrpc_set_keepalive(call);
413+
391414
_leave(" = %d [%u]", ret, call->peer->maxdata);
392415
return ret;
393416

0 commit comments

Comments
 (0)