| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* Management of Tx window, Tx resend, ACKs and out-of-sequence reception |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. |
|---|
| 4 | 5 | * Written by David Howells (dhowells@redhat.com) |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or |
|---|
| 7 | | - * modify it under the terms of the GNU General Public License |
|---|
| 8 | | - * as published by the Free Software Foundation; either version |
|---|
| 9 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 10 | 6 | */ |
|---|
| 11 | 7 | |
|---|
| 12 | 8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 47 | 43 | * propose an ACK be sent |
|---|
| 48 | 44 | */ |
|---|
| 49 | 45 | static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, |
|---|
| 50 | | - u16 skew, u32 serial, bool immediate, |
|---|
| 51 | | - bool background, |
|---|
| 46 | + u32 serial, bool immediate, bool background, |
|---|
| 52 | 47 | enum rxrpc_propose_ack_trace why) |
|---|
| 53 | 48 | { |
|---|
| 54 | 49 | enum rxrpc_propose_ack_outcome outcome = rxrpc_propose_ack_use; |
|---|
| .. | .. |
|---|
| 73 | 68 | if (RXRPC_ACK_UPDATEABLE & (1 << ack_reason)) { |
|---|
| 74 | 69 | outcome = rxrpc_propose_ack_update; |
|---|
| 75 | 70 | call->ackr_serial = serial; |
|---|
| 76 | | - call->ackr_skew = skew; |
|---|
| 77 | 71 | } |
|---|
| 78 | 72 | if (!immediate) |
|---|
| 79 | 73 | goto trace; |
|---|
| 80 | 74 | } else if (prior > rxrpc_ack_priority[call->ackr_reason]) { |
|---|
| 81 | 75 | call->ackr_reason = ack_reason; |
|---|
| 82 | 76 | call->ackr_serial = serial; |
|---|
| 83 | | - call->ackr_skew = skew; |
|---|
| 84 | 77 | } else { |
|---|
| 85 | 78 | outcome = rxrpc_propose_ack_subsume; |
|---|
| 86 | 79 | } |
|---|
| .. | .. |
|---|
| 118 | 111 | } else { |
|---|
| 119 | 112 | unsigned long now = jiffies, ack_at; |
|---|
| 120 | 113 | |
|---|
| 121 | | - if (call->peer->rtt_usage > 0) |
|---|
| 122 | | - ack_at = nsecs_to_jiffies(call->peer->rtt); |
|---|
| 114 | + if (call->peer->srtt_us != 0) |
|---|
| 115 | + ack_at = usecs_to_jiffies(call->peer->srtt_us >> 3); |
|---|
| 123 | 116 | else |
|---|
| 124 | 117 | ack_at = expiry; |
|---|
| 125 | 118 | |
|---|
| .. | .. |
|---|
| 141 | 134 | * propose an ACK be sent, locking the call structure |
|---|
| 142 | 135 | */ |
|---|
| 143 | 136 | void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, |
|---|
| 144 | | - u16 skew, u32 serial, bool immediate, bool background, |
|---|
| 137 | + u32 serial, bool immediate, bool background, |
|---|
| 145 | 138 | enum rxrpc_propose_ack_trace why) |
|---|
| 146 | 139 | { |
|---|
| 147 | 140 | spin_lock_bh(&call->lock); |
|---|
| 148 | | - __rxrpc_propose_ACK(call, ack_reason, skew, serial, |
|---|
| 141 | + __rxrpc_propose_ACK(call, ack_reason, serial, |
|---|
| 149 | 142 | immediate, background, why); |
|---|
| 150 | 143 | spin_unlock_bh(&call->lock); |
|---|
| 151 | 144 | } |
|---|
| .. | .. |
|---|
| 166 | 159 | struct sk_buff *skb; |
|---|
| 167 | 160 | unsigned long resend_at; |
|---|
| 168 | 161 | rxrpc_seq_t cursor, seq, top; |
|---|
| 169 | | - ktime_t now, max_age, oldest, ack_ts, timeout, min_timeo; |
|---|
| 162 | + ktime_t now, max_age, oldest, ack_ts; |
|---|
| 170 | 163 | int ix; |
|---|
| 171 | 164 | u8 annotation, anno_type, retrans = 0, unacked = 0; |
|---|
| 172 | 165 | |
|---|
| 173 | 166 | _enter("{%d,%d}", call->tx_hard_ack, call->tx_top); |
|---|
| 174 | 167 | |
|---|
| 175 | | - if (call->peer->rtt_usage > 1) |
|---|
| 176 | | - timeout = ns_to_ktime(call->peer->rtt * 3 / 2); |
|---|
| 177 | | - else |
|---|
| 178 | | - timeout = ms_to_ktime(rxrpc_resend_timeout); |
|---|
| 179 | | - min_timeo = ns_to_ktime((1000000000 / HZ) * 4); |
|---|
| 180 | | - if (ktime_before(timeout, min_timeo)) |
|---|
| 181 | | - timeout = min_timeo; |
|---|
| 182 | | - |
|---|
| 183 | 168 | now = ktime_get_real(); |
|---|
| 184 | | - max_age = ktime_sub(now, timeout); |
|---|
| 169 | + max_age = ktime_sub_us(now, jiffies_to_usecs(call->peer->rto_j)); |
|---|
| 185 | 170 | |
|---|
| 186 | 171 | spin_lock_bh(&call->lock); |
|---|
| 187 | 172 | |
|---|
| .. | .. |
|---|
| 206 | 191 | continue; |
|---|
| 207 | 192 | |
|---|
| 208 | 193 | skb = call->rxtx_buffer[ix]; |
|---|
| 209 | | - rxrpc_see_skb(skb, rxrpc_skb_tx_seen); |
|---|
| 194 | + rxrpc_see_skb(skb, rxrpc_skb_seen); |
|---|
| 210 | 195 | |
|---|
| 211 | 196 | if (anno_type == RXRPC_TX_ANNO_UNACK) { |
|---|
| 212 | 197 | if (ktime_after(skb->tstamp, max_age)) { |
|---|
| .. | .. |
|---|
| 226 | 211 | } |
|---|
| 227 | 212 | |
|---|
| 228 | 213 | resend_at = nsecs_to_jiffies(ktime_to_ns(ktime_sub(now, oldest))); |
|---|
| 229 | | - resend_at += jiffies + rxrpc_resend_timeout; |
|---|
| 214 | + resend_at += jiffies + rxrpc_get_rto_backoff(call->peer, retrans); |
|---|
| 230 | 215 | WRITE_ONCE(call->resend_at, resend_at); |
|---|
| 231 | 216 | |
|---|
| 232 | 217 | if (unacked) |
|---|
| .. | .. |
|---|
| 241 | 226 | rxrpc_timer_set_for_resend); |
|---|
| 242 | 227 | spin_unlock_bh(&call->lock); |
|---|
| 243 | 228 | ack_ts = ktime_sub(now, call->acks_latest_ts); |
|---|
| 244 | | - if (ktime_to_ns(ack_ts) < call->peer->rtt) |
|---|
| 229 | + if (ktime_to_us(ack_ts) < (call->peer->srtt_us >> 3)) |
|---|
| 245 | 230 | goto out; |
|---|
| 246 | | - rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false, |
|---|
| 231 | + rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false, |
|---|
| 247 | 232 | rxrpc_propose_ack_ping_for_lost_ack); |
|---|
| 248 | 233 | rxrpc_send_ack_packet(call, true, NULL); |
|---|
| 249 | 234 | goto out; |
|---|
| .. | .. |
|---|
| 261 | 246 | if (anno_type != RXRPC_TX_ANNO_RETRANS) |
|---|
| 262 | 247 | continue; |
|---|
| 263 | 248 | |
|---|
| 249 | + /* We need to reset the retransmission state, but we need to do |
|---|
| 250 | + * so before we drop the lock as a new ACK/NAK may come in and |
|---|
| 251 | + * confuse things |
|---|
| 252 | + */ |
|---|
| 253 | + annotation &= ~RXRPC_TX_ANNO_MASK; |
|---|
| 254 | + annotation |= RXRPC_TX_ANNO_UNACK | RXRPC_TX_ANNO_RESENT; |
|---|
| 255 | + call->rxtx_annotations[ix] = annotation; |
|---|
| 256 | + |
|---|
| 264 | 257 | skb = call->rxtx_buffer[ix]; |
|---|
| 265 | | - rxrpc_get_skb(skb, rxrpc_skb_tx_got); |
|---|
| 258 | + if (!skb) |
|---|
| 259 | + continue; |
|---|
| 260 | + |
|---|
| 261 | + rxrpc_get_skb(skb, rxrpc_skb_got); |
|---|
| 266 | 262 | spin_unlock_bh(&call->lock); |
|---|
| 267 | 263 | |
|---|
| 268 | 264 | if (rxrpc_send_data_packet(call, skb, true) < 0) { |
|---|
| 269 | | - rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
|---|
| 265 | + rxrpc_free_skb(skb, rxrpc_skb_freed); |
|---|
| 270 | 266 | return; |
|---|
| 271 | 267 | } |
|---|
| 272 | 268 | |
|---|
| 273 | 269 | if (rxrpc_is_client_call(call)) |
|---|
| 274 | 270 | rxrpc_expose_client_call(call); |
|---|
| 275 | 271 | |
|---|
| 276 | | - rxrpc_free_skb(skb, rxrpc_skb_tx_freed); |
|---|
| 272 | + rxrpc_free_skb(skb, rxrpc_skb_freed); |
|---|
| 277 | 273 | spin_lock_bh(&call->lock); |
|---|
| 278 | | - |
|---|
| 279 | | - /* We need to clear the retransmit state, but there are two |
|---|
| 280 | | - * things we need to be aware of: A new ACK/NAK might have been |
|---|
| 281 | | - * received and the packet might have been hard-ACK'd (in which |
|---|
| 282 | | - * case it will no longer be in the buffer). |
|---|
| 283 | | - */ |
|---|
| 284 | | - if (after(seq, call->tx_hard_ack)) { |
|---|
| 285 | | - annotation = call->rxtx_annotations[ix]; |
|---|
| 286 | | - anno_type = annotation & RXRPC_TX_ANNO_MASK; |
|---|
| 287 | | - if (anno_type == RXRPC_TX_ANNO_RETRANS || |
|---|
| 288 | | - anno_type == RXRPC_TX_ANNO_NAK) { |
|---|
| 289 | | - annotation &= ~RXRPC_TX_ANNO_MASK; |
|---|
| 290 | | - annotation |= RXRPC_TX_ANNO_UNACK; |
|---|
| 291 | | - } |
|---|
| 292 | | - annotation |= RXRPC_TX_ANNO_RESENT; |
|---|
| 293 | | - call->rxtx_annotations[ix] = annotation; |
|---|
| 294 | | - } |
|---|
| 295 | | - |
|---|
| 296 | 274 | if (after(call->tx_hard_ack, seq)) |
|---|
| 297 | 275 | seq = call->tx_hard_ack; |
|---|
| 298 | 276 | } |
|---|
| .. | .. |
|---|
| 332 | 310 | } |
|---|
| 333 | 311 | |
|---|
| 334 | 312 | if (call->state == RXRPC_CALL_COMPLETE) { |
|---|
| 335 | | - del_timer_sync(&call->timer); |
|---|
| 336 | | - rxrpc_notify_socket(call); |
|---|
| 313 | + rxrpc_delete_call_timer(call); |
|---|
| 337 | 314 | goto out_put; |
|---|
| 338 | 315 | } |
|---|
| 339 | 316 | |
|---|
| .. | .. |
|---|
| 376 | 353 | if (time_after_eq(now, t)) { |
|---|
| 377 | 354 | trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now); |
|---|
| 378 | 355 | cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET); |
|---|
| 379 | | - rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, true, |
|---|
| 356 | + rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, true, |
|---|
| 380 | 357 | rxrpc_propose_ack_ping_for_keepalive); |
|---|
| 381 | 358 | set_bit(RXRPC_CALL_EV_PING, &call->events); |
|---|
| 382 | 359 | } |
|---|
| .. | .. |
|---|
| 400 | 377 | if (test_bit(RXRPC_CALL_RX_HEARD, &call->flags) && |
|---|
| 401 | 378 | (int)call->conn->hi_serial - (int)call->rx_serial > 0) { |
|---|
| 402 | 379 | trace_rxrpc_call_reset(call); |
|---|
| 403 | | - rxrpc_abort_call("EXP", call, 0, RX_USER_ABORT, -ECONNRESET); |
|---|
| 380 | + rxrpc_abort_call("EXP", call, 0, RX_CALL_DEAD, -ECONNRESET); |
|---|
| 404 | 381 | } else { |
|---|
| 405 | | - rxrpc_abort_call("EXP", call, 0, RX_USER_ABORT, -ETIME); |
|---|
| 382 | + rxrpc_abort_call("EXP", call, 0, RX_CALL_TIMEOUT, -ETIME); |
|---|
| 406 | 383 | } |
|---|
| 407 | 384 | set_bit(RXRPC_CALL_EV_ABORT, &call->events); |
|---|
| 408 | 385 | goto recheck_state; |
|---|
| .. | .. |
|---|
| 411 | 388 | send_ack = NULL; |
|---|
| 412 | 389 | if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) { |
|---|
| 413 | 390 | call->acks_lost_top = call->tx_top; |
|---|
| 414 | | - rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false, |
|---|
| 391 | + rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false, |
|---|
| 415 | 392 | rxrpc_propose_ack_ping_for_lost_ack); |
|---|
| 416 | 393 | send_ack = &call->acks_lost_ping; |
|---|
| 417 | 394 | } |
|---|
| .. | .. |
|---|
| 429 | 406 | goto recheck_state; |
|---|
| 430 | 407 | } |
|---|
| 431 | 408 | |
|---|
| 432 | | - if (test_and_clear_bit(RXRPC_CALL_EV_RESEND, &call->events)) { |
|---|
| 409 | + if (test_and_clear_bit(RXRPC_CALL_EV_RESEND, &call->events) && |
|---|
| 410 | + call->state != RXRPC_CALL_CLIENT_RECV_REPLY) { |
|---|
| 433 | 411 | rxrpc_resend(call, now); |
|---|
| 434 | 412 | goto recheck_state; |
|---|
| 435 | 413 | } |
|---|