Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
17926a79 DH |
2 | /* Management of Tx window, Tx resend, ACKs and out-of-sequence reception |
3 | * | |
4 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | |
5 | * Written by David Howells (dhowells@redhat.com) | |
17926a79 DH |
6 | */ |
7 | ||
9b6d5398 JP |
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
9 | ||
17926a79 DH |
10 | #include <linux/module.h> |
11 | #include <linux/circ_buf.h> | |
12 | #include <linux/net.h> | |
13 | #include <linux/skbuff.h> | |
5a0e3ad6 | 14 | #include <linux/slab.h> |
17926a79 DH |
15 | #include <linux/udp.h> |
16 | #include <net/sock.h> | |
17 | #include <net/af_rxrpc.h> | |
18 | #include "ar-internal.h" | |
19 | ||
a5af7e1f DH |
20 | /* |
21 | * Propose a PING ACK be sent. | |
22 | */ | |
72f0c6fb DH |
23 | void rxrpc_propose_ping(struct rxrpc_call *call, u32 serial, |
24 | enum rxrpc_propose_ack_trace why) | |
a5af7e1f | 25 | { |
72f0c6fb DH |
26 | unsigned long now = jiffies; |
27 | unsigned long ping_at = now + rxrpc_idle_ack_delay; | |
a5af7e1f | 28 | |
72f0c6fb | 29 | if (time_before(ping_at, call->ping_at)) { |
d73f3a74 | 30 | call->ping_at = ping_at; |
72f0c6fb DH |
31 | rxrpc_reduce_call_timer(call, ping_at, now, |
32 | rxrpc_timer_set_for_ping); | |
530403d9 | 33 | trace_rxrpc_propose_ack(call, why, RXRPC_ACK_PING, serial); |
a5af7e1f DH |
34 | } |
35 | } | |
36 | ||
17926a79 | 37 | /* |
530403d9 | 38 | * Propose a DELAY ACK be sent in the future. |
17926a79 | 39 | */ |
4e76bd40 DH |
40 | void rxrpc_propose_delay_ACK(struct rxrpc_call *call, rxrpc_serial_t serial, |
41 | enum rxrpc_propose_ack_trace why) | |
17926a79 | 42 | { |
beb8e5e4 | 43 | unsigned long expiry = rxrpc_soft_ack_delay; |
72f0c6fb | 44 | unsigned long now = jiffies, ack_at; |
17926a79 | 45 | |
530403d9 DH |
46 | if (rxrpc_soft_ack_delay < expiry) |
47 | expiry = rxrpc_soft_ack_delay; | |
72f0c6fb DH |
48 | if (call->peer->srtt_us != 0) |
49 | ack_at = usecs_to_jiffies(call->peer->srtt_us >> 3); | |
50 | else | |
51 | ack_at = expiry; | |
52 | ||
53 | ack_at += READ_ONCE(call->tx_backoff); | |
54 | ack_at += now; | |
530403d9 | 55 | if (time_before(ack_at, call->delay_ack_at)) { |
d73f3a74 | 56 | call->delay_ack_at = ack_at; |
72f0c6fb DH |
57 | rxrpc_reduce_call_timer(call, ack_at, now, |
58 | rxrpc_timer_set_for_ack); | |
17926a79 | 59 | } |
9c7ad434 | 60 | |
530403d9 | 61 | trace_rxrpc_propose_ack(call, why, RXRPC_ACK_DELAY, serial); |
17926a79 DH |
62 | } |
63 | ||
57494343 DH |
64 | /* |
65 | * Handle congestion being detected by the retransmit timeout. | |
66 | */ | |
67 | static void rxrpc_congestion_timeout(struct rxrpc_call *call) | |
68 | { | |
69 | set_bit(RXRPC_CALL_RETRANS_TIMEOUT, &call->flags); | |
70 | } | |
71 | ||
17926a79 | 72 | /* |
248f219c | 73 | * Perform retransmission of NAK'd and unack'd packets. |
17926a79 | 74 | */ |
5e6ef4f1 | 75 | void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb) |
17926a79 | 76 | { |
d57a3a15 | 77 | struct rxrpc_ackpacket *ack = NULL; |
41b7fa15 | 78 | struct rxrpc_skb_priv *sp; |
a4ea4c47 | 79 | struct rxrpc_txbuf *txb; |
2c13c05c | 80 | unsigned long resend_at; |
693f9c13 | 81 | rxrpc_seq_t transmitted = call->tx_transmitted; |
c410bf01 | 82 | ktime_t now, max_age, oldest, ack_ts; |
a4ea4c47 | 83 | bool unacked = false; |
d57a3a15 | 84 | unsigned int i; |
a4ea4c47 | 85 | LIST_HEAD(retrans_queue); |
17926a79 | 86 | |
a4ea4c47 | 87 | _enter("{%d,%d}", call->acks_hard_ack, call->tx_top); |
17926a79 | 88 | |
a158bdd3 | 89 | now = ktime_get_real(); |
214a9dc7 | 90 | max_age = ktime_sub_us(now, jiffies_to_usecs(call->peer->rto_j)); |
d57a3a15 DH |
91 | oldest = now; |
92 | ||
d57a3a15 DH |
93 | if (list_empty(&call->tx_buffer)) |
94 | goto no_resend; | |
50235c4b | 95 | |
d57a3a15 DH |
96 | if (list_empty(&call->tx_buffer)) |
97 | goto no_further_resend; | |
98 | ||
5e6ef4f1 | 99 | trace_rxrpc_resend(call, ack_skb); |
d57a3a15 | 100 | txb = list_first_entry(&call->tx_buffer, struct rxrpc_txbuf, call_link); |
17926a79 | 101 | |
d57a3a15 DH |
102 | /* Scan the soft ACK table without dropping the lock and resend any |
103 | * explicitly NAK'd packets. | |
104 | */ | |
5e6ef4f1 | 105 | if (ack_skb) { |
41b7fa15 | 106 | sp = rxrpc_skb(ack_skb); |
5e6ef4f1 DH |
107 | ack = (void *)ack_skb->data + sizeof(struct rxrpc_wire_header); |
108 | ||
41b7fa15 | 109 | for (i = 0; i < sp->nr_acks; i++) { |
d57a3a15 | 110 | rxrpc_seq_t seq; |
17926a79 | 111 | |
d57a3a15 | 112 | if (ack->acks[i] & 1) |
248f219c | 113 | continue; |
41b7fa15 | 114 | seq = sp->first_ack + i; |
d57a3a15 DH |
115 | if (after(txb->seq, transmitted)) |
116 | break; | |
117 | if (after(txb->seq, seq)) | |
118 | continue; /* A new hard ACK probably came in */ | |
119 | list_for_each_entry_from(txb, &call->tx_buffer, call_link) { | |
120 | if (txb->seq == seq) | |
121 | goto found_txb; | |
122 | } | |
123 | goto no_further_resend; | |
124 | ||
125 | found_txb: | |
ba132d84 | 126 | if (after(txb->serial, call->acks_highest_serial)) |
d57a3a15 DH |
127 | continue; /* Ack point not yet reached */ |
128 | ||
129 | rxrpc_see_txbuf(txb, rxrpc_txbuf_see_unacked); | |
130 | ||
131 | if (list_empty(&txb->tx_link)) { | |
d57a3a15 | 132 | list_add_tail(&txb->tx_link, &retrans_queue); |
12bdff73 | 133 | txb->flags |= RXRPC_TXBUF_RESENT; |
33c40e24 | 134 | } |
d57a3a15 | 135 | |
ba132d84 | 136 | trace_rxrpc_retransmit(call, txb->seq, txb->serial, |
d57a3a15 DH |
137 | ktime_to_ns(ktime_sub(txb->last_sent, |
138 | max_age))); | |
139 | ||
140 | if (list_is_last(&txb->call_link, &call->tx_buffer)) | |
141 | goto no_further_resend; | |
142 | txb = list_next_entry(txb, call_link); | |
17926a79 | 143 | } |
d57a3a15 | 144 | } |
17926a79 | 145 | |
d57a3a15 DH |
146 | /* Fast-forward through the Tx queue to the point the peer says it has |
147 | * seen. Anything between the soft-ACK table and that point will get | |
148 | * ACK'd or NACK'd in due course, so don't worry about it here; here we | |
149 | * need to consider retransmitting anything beyond that point. | |
d57a3a15 | 150 | */ |
693f9c13 | 151 | if (after_eq(call->acks_prev_seq, call->tx_transmitted)) |
d57a3a15 DH |
152 | goto no_further_resend; |
153 | ||
154 | list_for_each_entry_from(txb, &call->tx_buffer, call_link) { | |
693f9c13 | 155 | if (before_eq(txb->seq, call->acks_prev_seq)) |
d57a3a15 | 156 | continue; |
693f9c13 | 157 | if (after(txb->seq, call->tx_transmitted)) |
d57a3a15 DH |
158 | break; /* Not transmitted yet */ |
159 | ||
160 | if (ack && ack->reason == RXRPC_ACK_PING_RESPONSE && | |
ba132d84 | 161 | before(txb->serial, ntohl(ack->serial))) |
d57a3a15 DH |
162 | goto do_resend; /* Wasn't accounted for by a more recent ping. */ |
163 | ||
164 | if (ktime_after(txb->last_sent, max_age)) { | |
165 | if (ktime_before(txb->last_sent, oldest)) | |
166 | oldest = txb->last_sent; | |
167 | continue; | |
168 | } | |
169 | ||
170 | do_resend: | |
171 | unacked = true; | |
172 | if (list_empty(&txb->tx_link)) { | |
d57a3a15 | 173 | list_add_tail(&txb->tx_link, &retrans_queue); |
12bdff73 | 174 | txb->flags |= RXRPC_TXBUF_RESENT; |
d57a3a15 DH |
175 | rxrpc_inc_stat(call->rxnet, stat_tx_data_retrans); |
176 | } | |
dfa7d920 | 177 | } |
248f219c | 178 | |
d57a3a15 | 179 | no_further_resend: |
d57a3a15 | 180 | no_resend: |
59299aa1 | 181 | resend_at = nsecs_to_jiffies(ktime_to_ns(ktime_sub(now, oldest))); |
a4ea4c47 DH |
182 | resend_at += jiffies + rxrpc_get_rto_backoff(call->peer, |
183 | !list_empty(&retrans_queue)); | |
d73f3a74 | 184 | call->resend_at = resend_at; |
248f219c | 185 | |
57494343 DH |
186 | if (unacked) |
187 | rxrpc_congestion_timeout(call); | |
188 | ||
189 | /* If there was nothing that needed retransmission then it's likely | |
190 | * that an ACK got lost somewhere. Send a ping to find out instead of | |
191 | * retransmitting data. | |
192 | */ | |
a4ea4c47 | 193 | if (list_empty(&retrans_queue)) { |
5e6ef4f1 | 194 | rxrpc_reduce_call_timer(call, resend_at, jiffies, |
a158bdd3 | 195 | rxrpc_timer_set_for_resend); |
57494343 | 196 | ack_ts = ktime_sub(now, call->acks_latest_ts); |
c410bf01 | 197 | if (ktime_to_us(ack_ts) < (call->peer->srtt_us >> 3)) |
57494343 | 198 | goto out; |
72f0c6fb DH |
199 | rxrpc_send_ACK(call, RXRPC_ACK_PING, 0, |
200 | rxrpc_propose_ack_ping_for_lost_ack); | |
57494343 DH |
201 | goto out; |
202 | } | |
203 | ||
5e6ef4f1 | 204 | /* Retransmit the queue */ |
a4ea4c47 DH |
205 | while ((txb = list_first_entry_or_null(&retrans_queue, |
206 | struct rxrpc_txbuf, tx_link))) { | |
207 | list_del_init(&txb->tx_link); | |
5e6ef4f1 | 208 | rxrpc_transmit_one(call, txb); |
dfa7d920 | 209 | } |
248f219c | 210 | |
57494343 | 211 | out: |
248f219c | 212 | _leave(""); |
17926a79 DH |
213 | } |
214 | ||
2d689424 DH |
215 | /* |
216 | * Start transmitting the reply to a service. This cancels the need to ACK the | |
217 | * request if we haven't yet done so. | |
218 | */ | |
219 | static void rxrpc_begin_service_reply(struct rxrpc_call *call) | |
220 | { | |
96b4059f | 221 | unsigned long now = jiffies; |
2d689424 | 222 | |
96b4059f | 223 | rxrpc_set_call_state(call, RXRPC_CALL_SERVER_SEND_REPLY); |
d73f3a74 | 224 | call->delay_ack_at = now + MAX_JIFFY_OFFSET; |
96b4059f DH |
225 | if (call->ackr_reason == RXRPC_ACK_DELAY) |
226 | call->ackr_reason = 0; | |
227 | trace_rxrpc_timer(call, rxrpc_timer_init_for_send_reply, now); | |
2d689424 DH |
228 | } |
229 | ||
230 | /* | |
231 | * Close the transmission phase. After this point there is no more data to be | |
232 | * transmitted in the call. | |
233 | */ | |
234 | static void rxrpc_close_tx_phase(struct rxrpc_call *call) | |
235 | { | |
236 | _debug("________awaiting reply/ACK__________"); | |
237 | ||
96b4059f | 238 | switch (__rxrpc_call_state(call)) { |
2d689424 | 239 | case RXRPC_CALL_CLIENT_SEND_REQUEST: |
96b4059f | 240 | rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_AWAIT_REPLY); |
2d689424 DH |
241 | break; |
242 | case RXRPC_CALL_SERVER_SEND_REPLY: | |
96b4059f | 243 | rxrpc_set_call_state(call, RXRPC_CALL_SERVER_AWAIT_ACK); |
2d689424 DH |
244 | break; |
245 | default: | |
246 | break; | |
247 | } | |
2d689424 DH |
248 | } |
249 | ||
cf37b598 DH |
250 | static bool rxrpc_tx_window_has_space(struct rxrpc_call *call) |
251 | { | |
252 | unsigned int winsize = min_t(unsigned int, call->tx_winsize, | |
253 | call->cong_cwnd + call->cong_extra); | |
254 | rxrpc_seq_t window = call->acks_hard_ack, wtop = window + winsize; | |
255 | rxrpc_seq_t tx_top = call->tx_top; | |
256 | int space; | |
257 | ||
258 | space = wtop - tx_top; | |
259 | return space > 0; | |
260 | } | |
261 | ||
262 | /* | |
263 | * Decant some if the sendmsg prepared queue into the transmission buffer. | |
264 | */ | |
265 | static void rxrpc_decant_prepared_tx(struct rxrpc_call *call) | |
266 | { | |
267 | struct rxrpc_txbuf *txb; | |
268 | ||
a343b174 DH |
269 | if (!test_bit(RXRPC_CALL_EXPOSED, &call->flags)) { |
270 | if (list_empty(&call->tx_sendmsg)) | |
271 | return; | |
cf37b598 | 272 | rxrpc_expose_client_call(call); |
a343b174 | 273 | } |
cf37b598 DH |
274 | |
275 | while ((txb = list_first_entry_or_null(&call->tx_sendmsg, | |
276 | struct rxrpc_txbuf, call_link))) { | |
277 | spin_lock(&call->tx_lock); | |
278 | list_del(&txb->call_link); | |
279 | spin_unlock(&call->tx_lock); | |
280 | ||
281 | call->tx_top = txb->seq; | |
282 | list_add_tail(&txb->call_link, &call->tx_buffer); | |
283 | ||
12bdff73 | 284 | if (txb->flags & RXRPC_LAST_PACKET) |
2d689424 DH |
285 | rxrpc_close_tx_phase(call); |
286 | ||
cf37b598 DH |
287 | rxrpc_transmit_one(call, txb); |
288 | ||
cf37b598 DH |
289 | if (!rxrpc_tx_window_has_space(call)) |
290 | break; | |
291 | } | |
292 | } | |
293 | ||
294 | static void rxrpc_transmit_some_data(struct rxrpc_call *call) | |
295 | { | |
96b4059f | 296 | switch (__rxrpc_call_state(call)) { |
cf37b598 DH |
297 | case RXRPC_CALL_SERVER_ACK_REQUEST: |
298 | if (list_empty(&call->tx_sendmsg)) | |
299 | return; | |
2d689424 | 300 | rxrpc_begin_service_reply(call); |
cf37b598 DH |
301 | fallthrough; |
302 | ||
303 | case RXRPC_CALL_SERVER_SEND_REPLY: | |
cf37b598 | 304 | case RXRPC_CALL_CLIENT_SEND_REQUEST: |
cf37b598 DH |
305 | if (!rxrpc_tx_window_has_space(call)) |
306 | return; | |
32cf8edb DH |
307 | if (list_empty(&call->tx_sendmsg)) { |
308 | rxrpc_inc_stat(call->rxnet, stat_tx_data_underflow); | |
cf37b598 | 309 | return; |
32cf8edb | 310 | } |
cf37b598 DH |
311 | rxrpc_decant_prepared_tx(call); |
312 | break; | |
313 | default: | |
314 | return; | |
315 | } | |
316 | } | |
317 | ||
5e6ef4f1 DH |
318 | /* |
319 | * Ping the other end to fill our RTT cache and to retrieve the rwind | |
320 | * and MTU parameters. | |
321 | */ | |
322 | static void rxrpc_send_initial_ping(struct rxrpc_call *call) | |
323 | { | |
324 | if (call->peer->rtt_count < 3 || | |
325 | ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), | |
326 | ktime_get_real())) | |
327 | rxrpc_send_ACK(call, RXRPC_ACK_PING, 0, | |
328 | rxrpc_propose_ack_ping_for_params); | |
329 | } | |
330 | ||
17926a79 | 331 | /* |
248f219c | 332 | * Handle retransmission and deferred ACK/abort generation. |
17926a79 | 333 | */ |
57af281e | 334 | bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb) |
17926a79 | 335 | { |
a158bdd3 | 336 | unsigned long now, next, t; |
5e6ef4f1 | 337 | bool resend = false, expired = false; |
a343b174 | 338 | s32 abort_code; |
17926a79 | 339 | |
cb0fc0c9 | 340 | rxrpc_see_call(call, rxrpc_call_see_input); |
e34d4234 | 341 | |
17926a79 | 342 | //printk("\n--------------------\n"); |
248f219c | 343 | _enter("{%d,%s,%lx}", |
96b4059f DH |
344 | call->debug_id, rxrpc_call_states[__rxrpc_call_state(call)], |
345 | call->events); | |
17926a79 | 346 | |
96b4059f | 347 | if (__rxrpc_call_is_complete(call)) |
5e6ef4f1 | 348 | goto out; |
17926a79 | 349 | |
a343b174 DH |
350 | /* Handle abort request locklessly, vs rxrpc_propose_abort(). */ |
351 | abort_code = smp_load_acquire(&call->send_abort); | |
352 | if (abort_code) { | |
57af281e DH |
353 | rxrpc_abort_call(call, 0, call->send_abort, call->send_abort_err, |
354 | call->send_abort_why); | |
a343b174 DH |
355 | goto out; |
356 | } | |
357 | ||
5e6ef4f1 | 358 | if (skb && skb->mark == RXRPC_SKB_MARK_ERROR) |
3feda9d6 | 359 | goto out; |
17926a79 | 360 | |
5e6ef4f1 | 361 | /* If we see our async-event poke, check for timeout trippage. */ |
a158bdd3 | 362 | now = jiffies; |
d73f3a74 | 363 | t = call->expect_rx_by; |
a158bdd3 DH |
364 | if (time_after_eq(now, t)) { |
365 | trace_rxrpc_timer(call, rxrpc_timer_exp_normal, now); | |
5e6ef4f1 | 366 | expired = true; |
a158bdd3 DH |
367 | } |
368 | ||
d73f3a74 | 369 | t = call->expect_req_by; |
96b4059f | 370 | if (__rxrpc_call_state(call) == RXRPC_CALL_SERVER_RECV_REQUEST && |
a158bdd3 DH |
371 | time_after_eq(now, t)) { |
372 | trace_rxrpc_timer(call, rxrpc_timer_exp_idle, now); | |
5e6ef4f1 | 373 | expired = true; |
a158bdd3 DH |
374 | } |
375 | ||
376 | t = READ_ONCE(call->expect_term_by); | |
377 | if (time_after_eq(now, t)) { | |
378 | trace_rxrpc_timer(call, rxrpc_timer_exp_hard, now); | |
5e6ef4f1 | 379 | expired = true; |
a158bdd3 DH |
380 | } |
381 | ||
d73f3a74 | 382 | t = call->delay_ack_at; |
a158bdd3 DH |
383 | if (time_after_eq(now, t)) { |
384 | trace_rxrpc_timer(call, rxrpc_timer_exp_ack, now); | |
d73f3a74 | 385 | call->delay_ack_at = now + MAX_JIFFY_OFFSET; |
e7870cf1 | 386 | rxrpc_send_ACK(call, RXRPC_ACK_DELAY, 0, |
530403d9 | 387 | rxrpc_propose_ack_ping_for_lost_ack); |
a158bdd3 DH |
388 | } |
389 | ||
d73f3a74 | 390 | t = call->ack_lost_at; |
bd1fdf8c DH |
391 | if (time_after_eq(now, t)) { |
392 | trace_rxrpc_timer(call, rxrpc_timer_exp_lost_ack, now); | |
d73f3a74 | 393 | call->ack_lost_at = now + MAX_JIFFY_OFFSET; |
bd1fdf8c DH |
394 | set_bit(RXRPC_CALL_EV_ACK_LOST, &call->events); |
395 | } | |
396 | ||
d73f3a74 | 397 | t = call->keepalive_at; |
415f44e4 DH |
398 | if (time_after_eq(now, t)) { |
399 | trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now); | |
d73f3a74 | 400 | call->keepalive_at = now + MAX_JIFFY_OFFSET; |
72f0c6fb DH |
401 | rxrpc_send_ACK(call, RXRPC_ACK_PING, 0, |
402 | rxrpc_propose_ack_ping_for_keepalive); | |
415f44e4 DH |
403 | } |
404 | ||
d73f3a74 | 405 | t = call->ping_at; |
a158bdd3 DH |
406 | if (time_after_eq(now, t)) { |
407 | trace_rxrpc_timer(call, rxrpc_timer_exp_ping, now); | |
d73f3a74 | 408 | call->ping_at = now + MAX_JIFFY_OFFSET; |
72f0c6fb DH |
409 | rxrpc_send_ACK(call, RXRPC_ACK_PING, 0, |
410 | rxrpc_propose_ack_ping_for_keepalive); | |
a158bdd3 DH |
411 | } |
412 | ||
d73f3a74 | 413 | t = call->resend_at; |
a158bdd3 DH |
414 | if (time_after_eq(now, t)) { |
415 | trace_rxrpc_timer(call, rxrpc_timer_exp_resend, now); | |
d73f3a74 | 416 | call->resend_at = now + MAX_JIFFY_OFFSET; |
5e6ef4f1 | 417 | resend = true; |
a158bdd3 DH |
418 | } |
419 | ||
5e6ef4f1 DH |
420 | if (skb) |
421 | rxrpc_input_call_packet(call, skb); | |
422 | ||
cf37b598 DH |
423 | rxrpc_transmit_some_data(call); |
424 | ||
5086d9a9 DH |
425 | if (skb) { |
426 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | |
427 | ||
428 | if (sp->hdr.type == RXRPC_PACKET_TYPE_ACK) | |
429 | rxrpc_congestion_degrade(call); | |
430 | } | |
431 | ||
5e6ef4f1 DH |
432 | if (test_and_clear_bit(RXRPC_CALL_EV_INITIAL_PING, &call->events)) |
433 | rxrpc_send_initial_ping(call); | |
434 | ||
a158bdd3 | 435 | /* Process events */ |
5e6ef4f1 | 436 | if (expired) { |
1a025028 DH |
437 | if (test_bit(RXRPC_CALL_RX_HEARD, &call->flags) && |
438 | (int)call->conn->hi_serial - (int)call->rx_serial > 0) { | |
439 | trace_rxrpc_call_reset(call); | |
57af281e DH |
440 | rxrpc_abort_call(call, 0, RX_CALL_DEAD, -ECONNRESET, |
441 | rxrpc_abort_call_reset); | |
1a025028 | 442 | } else { |
57af281e DH |
443 | rxrpc_abort_call(call, 0, RX_CALL_TIMEOUT, -ETIME, |
444 | rxrpc_abort_call_timeout); | |
1a025028 | 445 | } |
5e6ef4f1 | 446 | goto out; |
17926a79 DH |
447 | } |
448 | ||
5e6ef4f1 | 449 | if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) |
72f0c6fb DH |
450 | rxrpc_send_ACK(call, RXRPC_ACK_PING, 0, |
451 | rxrpc_propose_ack_ping_for_lost_ack); | |
a5af7e1f | 452 | |
96b4059f | 453 | if (resend && __rxrpc_call_state(call) != RXRPC_CALL_CLIENT_RECV_REPLY) |
5e6ef4f1 DH |
454 | rxrpc_resend(call, NULL); |
455 | ||
456 | if (test_and_clear_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags)) | |
457 | rxrpc_send_ACK(call, RXRPC_ACK_IDLE, 0, | |
458 | rxrpc_propose_ack_rx_idle); | |
459 | ||
5bbf9533 | 460 | if (call->ackr_nr_unacked > 2) { |
84e28aa5 DH |
461 | if (call->peer->rtt_count < 3) |
462 | rxrpc_send_ACK(call, RXRPC_ACK_PING, 0, | |
463 | rxrpc_propose_ack_ping_for_rtt); | |
464 | else if (ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), | |
465 | ktime_get_real())) | |
466 | rxrpc_send_ACK(call, RXRPC_ACK_PING, 0, | |
467 | rxrpc_propose_ack_ping_for_old_rtt); | |
468 | else | |
469 | rxrpc_send_ACK(call, RXRPC_ACK_IDLE, 0, | |
470 | rxrpc_propose_ack_input_data); | |
471 | } | |
17926a79 | 472 | |
a158bdd3 | 473 | /* Make sure the timer is restarted */ |
96b4059f | 474 | if (!__rxrpc_call_is_complete(call)) { |
5e6ef4f1 | 475 | next = call->expect_rx_by; |
a158bdd3 DH |
476 | |
477 | #define set(T) { t = READ_ONCE(T); if (time_before(t, next)) next = t; } | |
3d7682af | 478 | |
5e6ef4f1 DH |
479 | set(call->expect_req_by); |
480 | set(call->expect_term_by); | |
481 | set(call->delay_ack_at); | |
482 | set(call->ack_lost_at); | |
483 | set(call->resend_at); | |
484 | set(call->keepalive_at); | |
485 | set(call->ping_at); | |
a158bdd3 | 486 | |
5e6ef4f1 DH |
487 | now = jiffies; |
488 | if (time_after_eq(now, next)) | |
489 | rxrpc_poke_call(call, rxrpc_call_poke_timer_now); | |
17926a79 | 490 | |
5e6ef4f1 DH |
491 | rxrpc_reduce_call_timer(call, next, now, rxrpc_timer_restart); |
492 | } | |
17926a79 | 493 | |
248f219c | 494 | out: |
96b4059f | 495 | if (__rxrpc_call_is_complete(call)) { |
5e6ef4f1 | 496 | del_timer_sync(&call->timer); |
03fc55ad DH |
497 | if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) |
498 | rxrpc_disconnect_call(call); | |
499 | if (call->security) | |
500 | call->security->free_call_crypto(call); | |
501 | } | |
5e6ef4f1 DH |
502 | if (call->acks_hard_ack != call->tx_bottom) |
503 | rxrpc_shrink_call_tx_buffer(call); | |
17926a79 | 504 | _leave(""); |
57af281e | 505 | return true; |
17926a79 | 506 | } |