.. | .. |
---|
| 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(""); |
---|