| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* RxRPC packet transmission |
|---|
| 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 |
|---|
| .. | .. |
|---|
| 78 | 74 | u8 reason) |
|---|
| 79 | 75 | { |
|---|
| 80 | 76 | rxrpc_serial_t serial; |
|---|
| 77 | + unsigned int tmp; |
|---|
| 81 | 78 | rxrpc_seq_t hard_ack, top, seq; |
|---|
| 82 | 79 | int ix; |
|---|
| 83 | 80 | u32 mtu, jmax; |
|---|
| 84 | 81 | u8 *ackp = pkt->acks; |
|---|
| 82 | + |
|---|
| 83 | + tmp = atomic_xchg(&call->ackr_nr_unacked, 0); |
|---|
| 84 | + tmp |= atomic_xchg(&call->ackr_nr_consumed, 0); |
|---|
| 85 | + if (!tmp && (reason == RXRPC_ACK_DELAY || |
|---|
| 86 | + reason == RXRPC_ACK_IDLE)) |
|---|
| 87 | + return 0; |
|---|
| 85 | 88 | |
|---|
| 86 | 89 | /* Barrier against rxrpc_input_data(). */ |
|---|
| 87 | 90 | serial = call->ackr_serial; |
|---|
| .. | .. |
|---|
| 90 | 93 | *_hard_ack = hard_ack; |
|---|
| 91 | 94 | *_top = top; |
|---|
| 92 | 95 | |
|---|
| 93 | | - pkt->ack.bufferSpace = htons(8); |
|---|
| 94 | | - pkt->ack.maxSkew = htons(call->ackr_skew); |
|---|
| 96 | + pkt->ack.bufferSpace = htons(0); |
|---|
| 97 | + pkt->ack.maxSkew = htons(0); |
|---|
| 95 | 98 | pkt->ack.firstPacket = htonl(hard_ack + 1); |
|---|
| 96 | | - pkt->ack.previousPacket = htonl(call->ackr_prev_seq); |
|---|
| 99 | + pkt->ack.previousPacket = htonl(call->ackr_highest_seq); |
|---|
| 97 | 100 | pkt->ack.serial = htonl(serial); |
|---|
| 98 | 101 | pkt->ack.reason = reason; |
|---|
| 99 | 102 | pkt->ack.nAcks = top - hard_ack; |
|---|
| .. | .. |
|---|
| 128 | 131 | } |
|---|
| 129 | 132 | |
|---|
| 130 | 133 | /* |
|---|
| 134 | + * Record the beginning of an RTT probe. |
|---|
| 135 | + */ |
|---|
| 136 | +static int rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t serial, |
|---|
| 137 | + enum rxrpc_rtt_tx_trace why) |
|---|
| 138 | +{ |
|---|
| 139 | + unsigned long avail = call->rtt_avail; |
|---|
| 140 | + int rtt_slot = 9; |
|---|
| 141 | + |
|---|
| 142 | + if (!(avail & RXRPC_CALL_RTT_AVAIL_MASK)) |
|---|
| 143 | + goto no_slot; |
|---|
| 144 | + |
|---|
| 145 | + rtt_slot = __ffs(avail & RXRPC_CALL_RTT_AVAIL_MASK); |
|---|
| 146 | + if (!test_and_clear_bit(rtt_slot, &call->rtt_avail)) |
|---|
| 147 | + goto no_slot; |
|---|
| 148 | + |
|---|
| 149 | + call->rtt_serial[rtt_slot] = serial; |
|---|
| 150 | + call->rtt_sent_at[rtt_slot] = ktime_get_real(); |
|---|
| 151 | + smp_wmb(); /* Write data before avail bit */ |
|---|
| 152 | + set_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail); |
|---|
| 153 | + |
|---|
| 154 | + trace_rxrpc_rtt_tx(call, why, rtt_slot, serial); |
|---|
| 155 | + return rtt_slot; |
|---|
| 156 | + |
|---|
| 157 | +no_slot: |
|---|
| 158 | + trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_no_slot, rtt_slot, serial); |
|---|
| 159 | + return -1; |
|---|
| 160 | +} |
|---|
| 161 | + |
|---|
| 162 | +/* |
|---|
| 163 | + * Cancel an RTT probe. |
|---|
| 164 | + */ |
|---|
| 165 | +static void rxrpc_cancel_rtt_probe(struct rxrpc_call *call, |
|---|
| 166 | + rxrpc_serial_t serial, int rtt_slot) |
|---|
| 167 | +{ |
|---|
| 168 | + if (rtt_slot != -1) { |
|---|
| 169 | + clear_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail); |
|---|
| 170 | + smp_wmb(); /* Clear pending bit before setting slot */ |
|---|
| 171 | + set_bit(rtt_slot, &call->rtt_avail); |
|---|
| 172 | + trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_cancel, rtt_slot, serial); |
|---|
| 173 | + } |
|---|
| 174 | +} |
|---|
| 175 | + |
|---|
| 176 | +/* |
|---|
| 131 | 177 | * Send an ACK call packet. |
|---|
| 132 | 178 | */ |
|---|
| 133 | 179 | int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping, |
|---|
| .. | .. |
|---|
| 140 | 186 | rxrpc_serial_t serial; |
|---|
| 141 | 187 | rxrpc_seq_t hard_ack, top; |
|---|
| 142 | 188 | size_t len, n; |
|---|
| 143 | | - int ret; |
|---|
| 189 | + int ret, rtt_slot = -1; |
|---|
| 144 | 190 | u8 reason; |
|---|
| 145 | 191 | |
|---|
| 146 | 192 | if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) |
|---|
| .. | .. |
|---|
| 184 | 230 | n = rxrpc_fill_out_ack(conn, call, pkt, &hard_ack, &top, reason); |
|---|
| 185 | 231 | |
|---|
| 186 | 232 | spin_unlock_bh(&call->lock); |
|---|
| 233 | + if (n == 0) { |
|---|
| 234 | + kfree(pkt); |
|---|
| 235 | + return 0; |
|---|
| 236 | + } |
|---|
| 187 | 237 | |
|---|
| 188 | 238 | iov[0].iov_base = pkt; |
|---|
| 189 | 239 | iov[0].iov_len = sizeof(pkt->whdr) + sizeof(pkt->ack) + n; |
|---|
| .. | .. |
|---|
| 200 | 250 | if (_serial) |
|---|
| 201 | 251 | *_serial = serial; |
|---|
| 202 | 252 | |
|---|
| 203 | | - if (ping) { |
|---|
| 204 | | - call->ping_serial = serial; |
|---|
| 205 | | - smp_wmb(); |
|---|
| 206 | | - /* We need to stick a time in before we send the packet in case |
|---|
| 207 | | - * the reply gets back before kernel_sendmsg() completes - but |
|---|
| 208 | | - * asking UDP to send the packet can take a relatively long |
|---|
| 209 | | - * time. |
|---|
| 210 | | - */ |
|---|
| 211 | | - call->ping_time = ktime_get_real(); |
|---|
| 212 | | - set_bit(RXRPC_CALL_PINGING, &call->flags); |
|---|
| 213 | | - trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_ping, serial); |
|---|
| 214 | | - } |
|---|
| 253 | + if (ping) |
|---|
| 254 | + rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_ping); |
|---|
| 215 | 255 | |
|---|
| 216 | 256 | ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len); |
|---|
| 217 | 257 | conn->params.peer->last_tx_at = ktime_get_seconds(); |
|---|
| .. | .. |
|---|
| 225 | 265 | |
|---|
| 226 | 266 | if (call->state < RXRPC_CALL_COMPLETE) { |
|---|
| 227 | 267 | if (ret < 0) { |
|---|
| 228 | | - if (ping) |
|---|
| 229 | | - clear_bit(RXRPC_CALL_PINGING, &call->flags); |
|---|
| 268 | + rxrpc_cancel_rtt_probe(call, serial, rtt_slot); |
|---|
| 230 | 269 | rxrpc_propose_ACK(call, pkt->ack.reason, |
|---|
| 231 | | - ntohs(pkt->ack.maxSkew), |
|---|
| 232 | 270 | ntohl(pkt->ack.serial), |
|---|
| 233 | 271 | false, true, |
|---|
| 234 | 272 | rxrpc_propose_ack_retry_tx); |
|---|
| 235 | | - } else { |
|---|
| 236 | | - spin_lock_bh(&call->lock); |
|---|
| 237 | | - if (after(hard_ack, call->ackr_consumed)) |
|---|
| 238 | | - call->ackr_consumed = hard_ack; |
|---|
| 239 | | - if (after(top, call->ackr_seen)) |
|---|
| 240 | | - call->ackr_seen = top; |
|---|
| 241 | | - spin_unlock_bh(&call->lock); |
|---|
| 242 | 273 | } |
|---|
| 243 | 274 | |
|---|
| 244 | 275 | rxrpc_set_keepalive(call); |
|---|
| .. | .. |
|---|
| 326 | 357 | struct kvec iov[2]; |
|---|
| 327 | 358 | rxrpc_serial_t serial; |
|---|
| 328 | 359 | size_t len; |
|---|
| 329 | | - bool lost = false; |
|---|
| 330 | | - int ret, opt; |
|---|
| 360 | + int ret, rtt_slot = -1; |
|---|
| 331 | 361 | |
|---|
| 332 | 362 | _enter(",{%d}", skb->len); |
|---|
| 363 | + |
|---|
| 364 | + if (hlist_unhashed(&call->error_link)) { |
|---|
| 365 | + spin_lock_bh(&call->peer->lock); |
|---|
| 366 | + hlist_add_head_rcu(&call->error_link, &call->peer->error_targets); |
|---|
| 367 | + spin_unlock_bh(&call->peer->lock); |
|---|
| 368 | + } |
|---|
| 333 | 369 | |
|---|
| 334 | 370 | /* Each transmission of a Tx packet needs a new serial number */ |
|---|
| 335 | 371 | serial = atomic_inc_return(&conn->serial); |
|---|
| .. | .. |
|---|
| 375 | 411 | (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events) || |
|---|
| 376 | 412 | retrans || |
|---|
| 377 | 413 | call->cong_mode == RXRPC_CALL_SLOW_START || |
|---|
| 378 | | - (call->peer->rtt_usage < 3 && sp->hdr.seq & 1) || |
|---|
| 414 | + (call->peer->rtt_count < 3 && sp->hdr.seq & 1) || |
|---|
| 379 | 415 | ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), |
|---|
| 380 | 416 | ktime_get_real()))) |
|---|
| 381 | 417 | whdr.flags |= RXRPC_REQUEST_ACK; |
|---|
| .. | .. |
|---|
| 384 | 420 | static int lose; |
|---|
| 385 | 421 | if ((lose++ & 7) == 7) { |
|---|
| 386 | 422 | ret = 0; |
|---|
| 387 | | - lost = true; |
|---|
| 423 | + trace_rxrpc_tx_data(call, sp->hdr.seq, serial, |
|---|
| 424 | + whdr.flags, retrans, true); |
|---|
| 388 | 425 | goto done; |
|---|
| 389 | 426 | } |
|---|
| 390 | 427 | } |
|---|
| 391 | 428 | |
|---|
| 392 | | - _proto("Tx DATA %%%u { #%u }", serial, sp->hdr.seq); |
|---|
| 429 | + trace_rxrpc_tx_data(call, sp->hdr.seq, serial, whdr.flags, retrans, |
|---|
| 430 | + false); |
|---|
| 393 | 431 | |
|---|
| 394 | 432 | /* send the packet with the don't fragment bit set if we currently |
|---|
| 395 | 433 | * think it's small enough */ |
|---|
| .. | .. |
|---|
| 401 | 439 | sp->hdr.serial = serial; |
|---|
| 402 | 440 | smp_wmb(); /* Set serial before timestamp */ |
|---|
| 403 | 441 | skb->tstamp = ktime_get_real(); |
|---|
| 442 | + if (whdr.flags & RXRPC_REQUEST_ACK) |
|---|
| 443 | + rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_data); |
|---|
| 404 | 444 | |
|---|
| 405 | 445 | /* send the packet by UDP |
|---|
| 406 | 446 | * - returns -EMSGSIZE if UDP would have to fragment the packet |
|---|
| .. | .. |
|---|
| 412 | 452 | conn->params.peer->last_tx_at = ktime_get_seconds(); |
|---|
| 413 | 453 | |
|---|
| 414 | 454 | up_read(&conn->params.local->defrag_sem); |
|---|
| 415 | | - if (ret < 0) |
|---|
| 455 | + if (ret < 0) { |
|---|
| 456 | + rxrpc_cancel_rtt_probe(call, serial, rtt_slot); |
|---|
| 416 | 457 | trace_rxrpc_tx_fail(call->debug_id, serial, ret, |
|---|
| 417 | 458 | rxrpc_tx_point_call_data_nofrag); |
|---|
| 418 | | - else |
|---|
| 459 | + } else { |
|---|
| 419 | 460 | trace_rxrpc_tx_packet(call->debug_id, &whdr, |
|---|
| 420 | 461 | rxrpc_tx_point_call_data_nofrag); |
|---|
| 462 | + } |
|---|
| 463 | + |
|---|
| 421 | 464 | rxrpc_tx_backoff(call, ret); |
|---|
| 422 | 465 | if (ret == -EMSGSIZE) |
|---|
| 423 | 466 | goto send_fragmentable; |
|---|
| 424 | 467 | |
|---|
| 425 | 468 | done: |
|---|
| 426 | | - trace_rxrpc_tx_data(call, sp->hdr.seq, serial, whdr.flags, |
|---|
| 427 | | - retrans, lost); |
|---|
| 428 | 469 | if (ret >= 0) { |
|---|
| 429 | 470 | if (whdr.flags & RXRPC_REQUEST_ACK) { |
|---|
| 430 | 471 | call->peer->rtt_last_req = skb->tstamp; |
|---|
| 431 | | - trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_data, serial); |
|---|
| 432 | | - if (call->peer->rtt_usage > 1) { |
|---|
| 472 | + if (call->peer->rtt_count > 1) { |
|---|
| 433 | 473 | unsigned long nowj = jiffies, ack_lost_at; |
|---|
| 434 | 474 | |
|---|
| 435 | | - ack_lost_at = nsecs_to_jiffies(2 * call->peer->rtt); |
|---|
| 436 | | - if (ack_lost_at < 1) |
|---|
| 437 | | - ack_lost_at = 1; |
|---|
| 438 | | - |
|---|
| 475 | + ack_lost_at = rxrpc_get_rto_backoff(call->peer, false); |
|---|
| 439 | 476 | ack_lost_at += nowj; |
|---|
| 440 | 477 | WRITE_ONCE(call->ack_lost_at, ack_lost_at); |
|---|
| 441 | 478 | rxrpc_reduce_call_timer(call, ack_lost_at, nowj, |
|---|
| .. | .. |
|---|
| 478 | 515 | sp->hdr.serial = serial; |
|---|
| 479 | 516 | smp_wmb(); /* Set serial before timestamp */ |
|---|
| 480 | 517 | skb->tstamp = ktime_get_real(); |
|---|
| 518 | + if (whdr.flags & RXRPC_REQUEST_ACK) |
|---|
| 519 | + rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_data); |
|---|
| 481 | 520 | |
|---|
| 482 | 521 | switch (conn->params.local->srx.transport.family) { |
|---|
| 483 | 522 | case AF_INET6: |
|---|
| 484 | 523 | case AF_INET: |
|---|
| 485 | | - opt = IP_PMTUDISC_DONT; |
|---|
| 486 | | - kernel_setsockopt(conn->params.local->socket, |
|---|
| 487 | | - SOL_IP, IP_MTU_DISCOVER, |
|---|
| 488 | | - (char *)&opt, sizeof(opt)); |
|---|
| 524 | + ip_sock_set_mtu_discover(conn->params.local->socket->sk, |
|---|
| 525 | + IP_PMTUDISC_DONT); |
|---|
| 489 | 526 | ret = kernel_sendmsg(conn->params.local->socket, &msg, |
|---|
| 490 | 527 | iov, 2, len); |
|---|
| 491 | 528 | conn->params.peer->last_tx_at = ktime_get_seconds(); |
|---|
| 492 | 529 | |
|---|
| 493 | | - opt = IP_PMTUDISC_DO; |
|---|
| 494 | | - kernel_setsockopt(conn->params.local->socket, |
|---|
| 495 | | - SOL_IP, IP_MTU_DISCOVER, |
|---|
| 496 | | - (char *)&opt, sizeof(opt)); |
|---|
| 530 | + ip_sock_set_mtu_discover(conn->params.local->socket->sk, |
|---|
| 531 | + IP_PMTUDISC_DO); |
|---|
| 497 | 532 | break; |
|---|
| 498 | 533 | |
|---|
| 499 | 534 | default: |
|---|
| 500 | 535 | BUG(); |
|---|
| 501 | 536 | } |
|---|
| 502 | 537 | |
|---|
| 503 | | - if (ret < 0) |
|---|
| 538 | + if (ret < 0) { |
|---|
| 539 | + rxrpc_cancel_rtt_probe(call, serial, rtt_slot); |
|---|
| 504 | 540 | trace_rxrpc_tx_fail(call->debug_id, serial, ret, |
|---|
| 505 | 541 | rxrpc_tx_point_call_data_frag); |
|---|
| 506 | | - else |
|---|
| 542 | + } else { |
|---|
| 507 | 543 | trace_rxrpc_tx_packet(call->debug_id, &whdr, |
|---|
| 508 | 544 | rxrpc_tx_point_call_data_frag); |
|---|
| 545 | + } |
|---|
| 509 | 546 | rxrpc_tx_backoff(call, ret); |
|---|
| 510 | 547 | |
|---|
| 511 | 548 | up_write(&conn->params.local->defrag_sem); |
|---|
| .. | .. |
|---|
| 542 | 579 | memset(&whdr, 0, sizeof(whdr)); |
|---|
| 543 | 580 | |
|---|
| 544 | 581 | while ((skb = skb_dequeue(&local->reject_queue))) { |
|---|
| 545 | | - rxrpc_see_skb(skb, rxrpc_skb_rx_seen); |
|---|
| 582 | + rxrpc_see_skb(skb, rxrpc_skb_seen); |
|---|
| 546 | 583 | sp = rxrpc_skb(skb); |
|---|
| 547 | 584 | |
|---|
| 548 | 585 | switch (skb->mark) { |
|---|
| .. | .. |
|---|
| 558 | 595 | ioc = 2; |
|---|
| 559 | 596 | break; |
|---|
| 560 | 597 | default: |
|---|
| 561 | | - rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
|---|
| 598 | + rxrpc_free_skb(skb, rxrpc_skb_freed); |
|---|
| 562 | 599 | continue; |
|---|
| 563 | 600 | } |
|---|
| 564 | 601 | |
|---|
| 565 | | - if (rxrpc_extract_addr_from_skb(local, &srx, skb) == 0) { |
|---|
| 602 | + if (rxrpc_extract_addr_from_skb(&srx, skb) == 0) { |
|---|
| 566 | 603 | msg.msg_namelen = srx.transport_len; |
|---|
| 567 | 604 | |
|---|
| 568 | 605 | whdr.epoch = htonl(sp->hdr.epoch); |
|---|
| .. | .. |
|---|
| 583 | 620 | rxrpc_tx_point_reject); |
|---|
| 584 | 621 | } |
|---|
| 585 | 622 | |
|---|
| 586 | | - rxrpc_free_skb(skb, rxrpc_skb_rx_freed); |
|---|
| 623 | + rxrpc_free_skb(skb, rxrpc_skb_freed); |
|---|
| 587 | 624 | } |
|---|
| 588 | 625 | |
|---|
| 589 | 626 | _leave(""); |
|---|