12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 28c3e34a4SDavid Howells /* RxRPC packet transmission 38c3e34a4SDavid Howells * 48c3e34a4SDavid Howells * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 58c3e34a4SDavid Howells * Written by David Howells (dhowells@redhat.com) 68c3e34a4SDavid Howells */ 78c3e34a4SDavid Howells 88c3e34a4SDavid Howells #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 98c3e34a4SDavid Howells 108c3e34a4SDavid Howells #include <linux/net.h> 118c3e34a4SDavid Howells #include <linux/gfp.h> 128c3e34a4SDavid Howells #include <linux/skbuff.h> 138c3e34a4SDavid Howells #include <linux/export.h> 148c3e34a4SDavid Howells #include <net/sock.h> 158c3e34a4SDavid Howells #include <net/af_rxrpc.h> 16ed472b0cSDavid Howells #include <net/udp.h> 178c3e34a4SDavid Howells #include "ar-internal.h" 188c3e34a4SDavid Howells 19ed472b0cSDavid Howells extern int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len); 20ed472b0cSDavid Howells 216423ac2eSDavid Howells static ssize_t do_udp_sendmsg(struct socket *socket, struct msghdr *msg, size_t len) 22ed472b0cSDavid Howells { 23ed472b0cSDavid Howells struct sockaddr *sa = msg->msg_name; 246423ac2eSDavid Howells struct sock *sk = socket->sk; 25ed472b0cSDavid Howells 266423ac2eSDavid Howells if (IS_ENABLED(CONFIG_AF_RXRPC_IPV6)) { 276423ac2eSDavid Howells if (sa->sa_family == AF_INET6) { 286423ac2eSDavid Howells if (sk->sk_family != AF_INET6) { 296423ac2eSDavid Howells pr_warn("AF_INET6 address on AF_INET socket\n"); 306423ac2eSDavid Howells return -ENOPROTOOPT; 316423ac2eSDavid Howells } 326423ac2eSDavid Howells return udpv6_sendmsg(sk, msg, len); 336423ac2eSDavid Howells } 346423ac2eSDavid Howells } 356423ac2eSDavid Howells return udp_sendmsg(sk, msg, len); 36ed472b0cSDavid Howells } 37ed472b0cSDavid Howells 3826cb02aaSDavid Howells struct rxrpc_abort_buffer { 3926cb02aaSDavid Howells struct rxrpc_wire_header whdr; 4026cb02aaSDavid Howells __be32 abort_code; 4126cb02aaSDavid Howells }; 4226cb02aaSDavid Howells 43ace45becSDavid Howells static const char rxrpc_keepalive_string[] = ""; 44ace45becSDavid Howells 458d94aa38SDavid Howells /* 46c7e86acfSDavid Howells * Increase Tx backoff on transmission failure and clear it on success. 47c7e86acfSDavid Howells */ 48c7e86acfSDavid Howells static void rxrpc_tx_backoff(struct rxrpc_call *call, int ret) 49c7e86acfSDavid Howells { 50c7e86acfSDavid Howells if (ret < 0) { 51c7e86acfSDavid Howells u16 tx_backoff = READ_ONCE(call->tx_backoff); 52c7e86acfSDavid Howells 53c7e86acfSDavid Howells if (tx_backoff < HZ) 54c7e86acfSDavid Howells WRITE_ONCE(call->tx_backoff, tx_backoff + 1); 55c7e86acfSDavid Howells } else { 56c7e86acfSDavid Howells WRITE_ONCE(call->tx_backoff, 0); 57c7e86acfSDavid Howells } 58c7e86acfSDavid Howells } 59c7e86acfSDavid Howells 60c7e86acfSDavid Howells /* 61415f44e4SDavid Howells * Arrange for a keepalive ping a certain time after we last transmitted. This 62415f44e4SDavid Howells * lets the far side know we're still interested in this call and helps keep 63415f44e4SDavid Howells * the route through any intervening firewall open. 64415f44e4SDavid Howells * 65415f44e4SDavid Howells * Receiving a response to the ping will prevent the ->expect_rx_by timer from 66415f44e4SDavid Howells * expiring. 67415f44e4SDavid Howells */ 68415f44e4SDavid Howells static void rxrpc_set_keepalive(struct rxrpc_call *call) 69415f44e4SDavid Howells { 70415f44e4SDavid Howells unsigned long now = jiffies, keepalive_at = call->next_rx_timo / 6; 71415f44e4SDavid Howells 72415f44e4SDavid Howells keepalive_at += now; 73415f44e4SDavid Howells WRITE_ONCE(call->keepalive_at, keepalive_at); 74415f44e4SDavid Howells rxrpc_reduce_call_timer(call, keepalive_at, now, 75415f44e4SDavid Howells rxrpc_timer_set_for_keepalive); 76415f44e4SDavid Howells } 77415f44e4SDavid Howells 78415f44e4SDavid Howells /* 798d94aa38SDavid Howells * Fill out an ACK packet. 808d94aa38SDavid Howells */ 811457cc4cSDavid Howells static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn, 821457cc4cSDavid Howells struct rxrpc_call *call, 835d7edbc9SDavid Howells struct rxrpc_txbuf *txb) 848d94aa38SDavid Howells { 8572f0c6fbSDavid Howells struct rxrpc_ackinfo ackinfo; 865d7edbc9SDavid Howells unsigned int qsize; 875d7edbc9SDavid Howells rxrpc_seq_t window, wtop, wrap_point, ix, first; 885d7edbc9SDavid Howells int rsize; 895d7edbc9SDavid Howells u64 wtmp; 908d94aa38SDavid Howells u32 mtu, jmax; 9172f0c6fbSDavid Howells u8 *ackp = txb->acks; 925d7edbc9SDavid Howells u8 sack_buffer[sizeof(call->ackr_sack_table)] __aligned(8); 938d94aa38SDavid Howells 945d7edbc9SDavid Howells atomic_set(&call->ackr_nr_unacked, 0); 955d7edbc9SDavid Howells atomic_set(&call->ackr_nr_consumed, 0); 96f2a676d1SDavid Howells rxrpc_inc_stat(call->rxnet, stat_tx_ack_fill); 979a3dedcfSDavid Howells 98248f219cSDavid Howells /* Barrier against rxrpc_input_data(). */ 995d7edbc9SDavid Howells retry: 1005d7edbc9SDavid Howells wtmp = atomic64_read_acquire(&call->ackr_window); 1015d7edbc9SDavid Howells window = lower_32_bits(wtmp); 1025d7edbc9SDavid Howells wtop = upper_32_bits(wtmp); 1035d7edbc9SDavid Howells txb->ack.firstPacket = htonl(window); 1045d7edbc9SDavid Howells txb->ack.nAcks = 0; 105248f219cSDavid Howells 1065d7edbc9SDavid Howells if (after(wtop, window)) { 1075d7edbc9SDavid Howells /* Try to copy the SACK ring locklessly. We can use the copy, 1085d7edbc9SDavid Howells * only if the now-current top of the window didn't go past the 1095d7edbc9SDavid Howells * previously read base - otherwise we can't know whether we 1105d7edbc9SDavid Howells * have old data or new data. 1115d7edbc9SDavid Howells */ 1125d7edbc9SDavid Howells memcpy(sack_buffer, call->ackr_sack_table, sizeof(sack_buffer)); 1135d7edbc9SDavid Howells wrap_point = window + RXRPC_SACK_SIZE - 1; 1145d7edbc9SDavid Howells wtmp = atomic64_read_acquire(&call->ackr_window); 1155d7edbc9SDavid Howells window = lower_32_bits(wtmp); 1165d7edbc9SDavid Howells wtop = upper_32_bits(wtmp); 1175d7edbc9SDavid Howells if (after(wtop, wrap_point)) { 1185d7edbc9SDavid Howells cond_resched(); 1195d7edbc9SDavid Howells goto retry; 1205d7edbc9SDavid Howells } 1218d94aa38SDavid Howells 1225d7edbc9SDavid Howells /* The buffer is maintained as a ring with an invariant mapping 1235d7edbc9SDavid Howells * between bit position and sequence number, so we'll probably 1245d7edbc9SDavid Howells * need to rotate it. 1255d7edbc9SDavid Howells */ 1265d7edbc9SDavid Howells txb->ack.nAcks = wtop - window; 1275d7edbc9SDavid Howells ix = window % RXRPC_SACK_SIZE; 1285d7edbc9SDavid Howells first = sizeof(sack_buffer) - ix; 1295d7edbc9SDavid Howells 1305d7edbc9SDavid Howells if (ix + txb->ack.nAcks <= RXRPC_SACK_SIZE) { 1315d7edbc9SDavid Howells memcpy(txb->acks, sack_buffer + ix, txb->ack.nAcks); 1325d7edbc9SDavid Howells } else { 1335d7edbc9SDavid Howells memcpy(txb->acks, sack_buffer + ix, first); 1345d7edbc9SDavid Howells memcpy(txb->acks + first, sack_buffer, 1355d7edbc9SDavid Howells txb->ack.nAcks - first); 1365d7edbc9SDavid Howells } 1375d7edbc9SDavid Howells 1385d7edbc9SDavid Howells ackp += txb->ack.nAcks; 1395d7edbc9SDavid Howells } else if (before(wtop, window)) { 1405d7edbc9SDavid Howells pr_warn("ack window backward %x %x", window, wtop); 141530403d9SDavid Howells } else if (txb->ack.reason == RXRPC_ACK_DELAY) { 142530403d9SDavid Howells txb->ack.reason = RXRPC_ACK_IDLE; 143248f219cSDavid Howells } 144248f219cSDavid Howells 1452cc80086SDavid Howells mtu = conn->peer->if_mtu; 1462cc80086SDavid Howells mtu -= conn->peer->hdrsize; 147d4d02d8bSDavid Howells jmax = rxrpc_rx_jumbo_max; 1485d7edbc9SDavid Howells qsize = (window - 1) - call->rx_consumed; 1495d7edbc9SDavid Howells rsize = max_t(int, call->rx_winsize - qsize, 0); 15072f0c6fbSDavid Howells ackinfo.rxMTU = htonl(rxrpc_rx_mtu); 15172f0c6fbSDavid Howells ackinfo.maxMTU = htonl(mtu); 1525d7edbc9SDavid Howells ackinfo.rwind = htonl(rsize); 15372f0c6fbSDavid Howells ackinfo.jumbo_max = htonl(jmax); 1548d94aa38SDavid Howells 1558d94aa38SDavid Howells *ackp++ = 0; 1568d94aa38SDavid Howells *ackp++ = 0; 1578d94aa38SDavid Howells *ackp++ = 0; 15872f0c6fbSDavid Howells memcpy(ackp, &ackinfo, sizeof(ackinfo)); 1595d7edbc9SDavid Howells return txb->ack.nAcks + 3 + sizeof(ackinfo); 1608d94aa38SDavid Howells } 1618d94aa38SDavid Howells 1628d94aa38SDavid Howells /* 1634700c4d8SDavid Howells * Record the beginning of an RTT probe. 1644700c4d8SDavid Howells */ 1654700c4d8SDavid Howells static int rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t serial, 1664700c4d8SDavid Howells enum rxrpc_rtt_tx_trace why) 1674700c4d8SDavid Howells { 1684700c4d8SDavid Howells unsigned long avail = call->rtt_avail; 1694700c4d8SDavid Howells int rtt_slot = 9; 1704700c4d8SDavid Howells 1714700c4d8SDavid Howells if (!(avail & RXRPC_CALL_RTT_AVAIL_MASK)) 1724700c4d8SDavid Howells goto no_slot; 1734700c4d8SDavid Howells 1744700c4d8SDavid Howells rtt_slot = __ffs(avail & RXRPC_CALL_RTT_AVAIL_MASK); 1754700c4d8SDavid Howells if (!test_and_clear_bit(rtt_slot, &call->rtt_avail)) 1764700c4d8SDavid Howells goto no_slot; 1774700c4d8SDavid Howells 1784700c4d8SDavid Howells call->rtt_serial[rtt_slot] = serial; 1794700c4d8SDavid Howells call->rtt_sent_at[rtt_slot] = ktime_get_real(); 1804700c4d8SDavid Howells smp_wmb(); /* Write data before avail bit */ 1814700c4d8SDavid Howells set_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail); 1824700c4d8SDavid Howells 1834700c4d8SDavid Howells trace_rxrpc_rtt_tx(call, why, rtt_slot, serial); 1844700c4d8SDavid Howells return rtt_slot; 1854700c4d8SDavid Howells 1864700c4d8SDavid Howells no_slot: 1874700c4d8SDavid Howells trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_no_slot, rtt_slot, serial); 1884700c4d8SDavid Howells return -1; 1894700c4d8SDavid Howells } 1904700c4d8SDavid Howells 1914700c4d8SDavid Howells /* 1924700c4d8SDavid Howells * Cancel an RTT probe. 1934700c4d8SDavid Howells */ 1944700c4d8SDavid Howells static void rxrpc_cancel_rtt_probe(struct rxrpc_call *call, 1954700c4d8SDavid Howells rxrpc_serial_t serial, int rtt_slot) 1964700c4d8SDavid Howells { 1974700c4d8SDavid Howells if (rtt_slot != -1) { 1984700c4d8SDavid Howells clear_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail); 1994700c4d8SDavid Howells smp_wmb(); /* Clear pending bit before setting slot */ 2004700c4d8SDavid Howells set_bit(rtt_slot, &call->rtt_avail); 2014700c4d8SDavid Howells trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_cancel, rtt_slot, serial); 2024700c4d8SDavid Howells } 2034700c4d8SDavid Howells } 2044700c4d8SDavid Howells 2054700c4d8SDavid Howells /* 20626cb02aaSDavid Howells * Send an ACK call packet. 2078d94aa38SDavid Howells */ 20872f0c6fbSDavid Howells static int rxrpc_send_ack_packet(struct rxrpc_local *local, struct rxrpc_txbuf *txb) 2098d94aa38SDavid Howells { 2105273a191SDavid Howells struct rxrpc_connection *conn; 21172f0c6fbSDavid Howells struct rxrpc_call *call = txb->call; 2128d94aa38SDavid Howells struct msghdr msg; 21372f0c6fbSDavid Howells struct kvec iov[1]; 2148d94aa38SDavid Howells rxrpc_serial_t serial; 2158d94aa38SDavid Howells size_t len, n; 2164700c4d8SDavid Howells int ret, rtt_slot = -1; 2178d94aa38SDavid Howells 2185273a191SDavid Howells if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) 2198d94aa38SDavid Howells return -ECONNRESET; 2208d94aa38SDavid Howells 2215273a191SDavid Howells conn = call->conn; 2228d94aa38SDavid Howells 2238d94aa38SDavid Howells msg.msg_name = &call->peer->srx.transport; 2248d94aa38SDavid Howells msg.msg_namelen = call->peer->srx.transport_len; 2258d94aa38SDavid Howells msg.msg_control = NULL; 2268d94aa38SDavid Howells msg.msg_controllen = 0; 2278d94aa38SDavid Howells msg.msg_flags = 0; 2288d94aa38SDavid Howells 22972f0c6fbSDavid Howells if (txb->ack.reason == RXRPC_ACK_PING) 23072f0c6fbSDavid Howells txb->wire.flags |= RXRPC_REQUEST_ACK; 2318d94aa38SDavid Howells 2325d7edbc9SDavid Howells n = rxrpc_fill_out_ack(conn, call, txb); 2334e76bd40SDavid Howells if (n == 0) 2349a3dedcfSDavid Howells return 0; 2358d94aa38SDavid Howells 23672f0c6fbSDavid Howells iov[0].iov_base = &txb->wire; 23772f0c6fbSDavid Howells iov[0].iov_len = sizeof(txb->wire) + sizeof(txb->ack) + n; 23872f0c6fbSDavid Howells len = iov[0].iov_len; 2398d94aa38SDavid Howells 240b86e218eSDavid Howells serial = atomic_inc_return(&conn->serial); 24172f0c6fbSDavid Howells txb->wire.serial = htonl(serial); 2424764c0daSDavid Howells trace_rxrpc_tx_ack(call->debug_id, serial, 24372f0c6fbSDavid Howells ntohl(txb->ack.firstPacket), 24472f0c6fbSDavid Howells ntohl(txb->ack.serial), txb->ack.reason, txb->ack.nAcks); 245b86e218eSDavid Howells 24672f0c6fbSDavid Howells if (txb->ack.reason == RXRPC_ACK_PING) 2474700c4d8SDavid Howells rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_ping); 24826cb02aaSDavid Howells 249f2a676d1SDavid Howells rxrpc_inc_stat(call->rxnet, stat_tx_ack_send); 250ed472b0cSDavid Howells 2515d7edbc9SDavid Howells /* Grab the highest received seq as late as possible */ 2525d7edbc9SDavid Howells txb->ack.previousPacket = htonl(call->rx_highest_seq); 2535d7edbc9SDavid Howells 25472f0c6fbSDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, len); 2552cc80086SDavid Howells ret = do_udp_sendmsg(conn->local->socket, &msg, len); 256ed472b0cSDavid Howells call->peer->last_tx_at = ktime_get_seconds(); 2576b47fe1dSDavid Howells if (ret < 0) 2586b47fe1dSDavid Howells trace_rxrpc_tx_fail(call->debug_id, serial, ret, 2594764c0daSDavid Howells rxrpc_tx_point_call_ack); 2604764c0daSDavid Howells else 26172f0c6fbSDavid Howells trace_rxrpc_tx_packet(call->debug_id, &txb->wire, 2624764c0daSDavid Howells rxrpc_tx_point_call_ack); 263c7e86acfSDavid Howells rxrpc_tx_backoff(call, ret); 2648d94aa38SDavid Howells 26526cb02aaSDavid Howells if (call->state < RXRPC_CALL_COMPLETE) { 26672f0c6fbSDavid Howells if (ret < 0) 2674700c4d8SDavid Howells rxrpc_cancel_rtt_probe(call, serial, rtt_slot); 268415f44e4SDavid Howells rxrpc_set_keepalive(call); 269248f219cSDavid Howells } 270248f219cSDavid Howells 2718d94aa38SDavid Howells return ret; 2728d94aa38SDavid Howells } 2738d94aa38SDavid Howells 2748c3e34a4SDavid Howells /* 27572f0c6fbSDavid Howells * ACK transmitter for a local endpoint. The UDP socket locks around each 27672f0c6fbSDavid Howells * transmission, so we can only transmit one packet at a time, ACK, DATA or 27772f0c6fbSDavid Howells * otherwise. 27872f0c6fbSDavid Howells */ 27972f0c6fbSDavid Howells void rxrpc_transmit_ack_packets(struct rxrpc_local *local) 28072f0c6fbSDavid Howells { 28172f0c6fbSDavid Howells LIST_HEAD(queue); 28272f0c6fbSDavid Howells int ret; 28372f0c6fbSDavid Howells 2840fde882fSDavid Howells rxrpc_see_local(local, rxrpc_local_see_tx_ack); 28572f0c6fbSDavid Howells 28672f0c6fbSDavid Howells if (list_empty(&local->ack_tx_queue)) 28772f0c6fbSDavid Howells return; 28872f0c6fbSDavid Howells 28972f0c6fbSDavid Howells spin_lock_bh(&local->ack_tx_lock); 29072f0c6fbSDavid Howells list_splice_tail_init(&local->ack_tx_queue, &queue); 29172f0c6fbSDavid Howells spin_unlock_bh(&local->ack_tx_lock); 29272f0c6fbSDavid Howells 29372f0c6fbSDavid Howells while (!list_empty(&queue)) { 29472f0c6fbSDavid Howells struct rxrpc_txbuf *txb = 29572f0c6fbSDavid Howells list_entry(queue.next, struct rxrpc_txbuf, tx_link); 29672f0c6fbSDavid Howells 29772f0c6fbSDavid Howells ret = rxrpc_send_ack_packet(local, txb); 29872f0c6fbSDavid Howells if (ret < 0 && ret != -ECONNRESET) { 29972f0c6fbSDavid Howells spin_lock_bh(&local->ack_tx_lock); 30072f0c6fbSDavid Howells list_splice_init(&queue, &local->ack_tx_queue); 30172f0c6fbSDavid Howells spin_unlock_bh(&local->ack_tx_lock); 30272f0c6fbSDavid Howells break; 30372f0c6fbSDavid Howells } 30472f0c6fbSDavid Howells 30572f0c6fbSDavid Howells list_del_init(&txb->tx_link); 306cb0fc0c9SDavid Howells rxrpc_put_call(txb->call, rxrpc_call_put_send_ack); 30772f0c6fbSDavid Howells rxrpc_put_txbuf(txb, rxrpc_txbuf_put_ack_tx); 30872f0c6fbSDavid Howells } 30972f0c6fbSDavid Howells } 31072f0c6fbSDavid Howells 31172f0c6fbSDavid Howells /* 31226cb02aaSDavid Howells * Send an ABORT call packet. 31326cb02aaSDavid Howells */ 31426cb02aaSDavid Howells int rxrpc_send_abort_packet(struct rxrpc_call *call) 31526cb02aaSDavid Howells { 3165273a191SDavid Howells struct rxrpc_connection *conn; 31726cb02aaSDavid Howells struct rxrpc_abort_buffer pkt; 31826cb02aaSDavid Howells struct msghdr msg; 31926cb02aaSDavid Howells struct kvec iov[1]; 32026cb02aaSDavid Howells rxrpc_serial_t serial; 32126cb02aaSDavid Howells int ret; 32226cb02aaSDavid Howells 323dcbefc30SDavid Howells /* Don't bother sending aborts for a client call once the server has 324dcbefc30SDavid Howells * hard-ACK'd all of its request data. After that point, we're not 325dcbefc30SDavid Howells * going to stop the operation proceeding, and whilst we might limit 326dcbefc30SDavid Howells * the reply, it's not worth it if we can send a new call on the same 327dcbefc30SDavid Howells * channel instead, thereby closing off this call. 328dcbefc30SDavid Howells */ 329dcbefc30SDavid Howells if (rxrpc_is_client_call(call) && 330a4ea4c47SDavid Howells test_bit(RXRPC_CALL_TX_ALL_ACKED, &call->flags)) 331dcbefc30SDavid Howells return 0; 332dcbefc30SDavid Howells 3335273a191SDavid Howells if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) 33426cb02aaSDavid Howells return -ECONNRESET; 33526cb02aaSDavid Howells 3365273a191SDavid Howells conn = call->conn; 3375273a191SDavid Howells 33826cb02aaSDavid Howells msg.msg_name = &call->peer->srx.transport; 33926cb02aaSDavid Howells msg.msg_namelen = call->peer->srx.transport_len; 34026cb02aaSDavid Howells msg.msg_control = NULL; 34126cb02aaSDavid Howells msg.msg_controllen = 0; 34226cb02aaSDavid Howells msg.msg_flags = 0; 34326cb02aaSDavid Howells 34426cb02aaSDavid Howells pkt.whdr.epoch = htonl(conn->proto.epoch); 34526cb02aaSDavid Howells pkt.whdr.cid = htonl(call->cid); 34626cb02aaSDavid Howells pkt.whdr.callNumber = htonl(call->call_id); 34726cb02aaSDavid Howells pkt.whdr.seq = 0; 34826cb02aaSDavid Howells pkt.whdr.type = RXRPC_PACKET_TYPE_ABORT; 34926cb02aaSDavid Howells pkt.whdr.flags = conn->out_clientflag; 35026cb02aaSDavid Howells pkt.whdr.userStatus = 0; 35126cb02aaSDavid Howells pkt.whdr.securityIndex = call->security_ix; 35226cb02aaSDavid Howells pkt.whdr._rsvd = 0; 353f3441d41SDavid Howells pkt.whdr.serviceId = htons(call->dest_srx.srx_service); 35426cb02aaSDavid Howells pkt.abort_code = htonl(call->abort_code); 35526cb02aaSDavid Howells 35626cb02aaSDavid Howells iov[0].iov_base = &pkt; 35726cb02aaSDavid Howells iov[0].iov_len = sizeof(pkt); 35826cb02aaSDavid Howells 35926cb02aaSDavid Howells serial = atomic_inc_return(&conn->serial); 36026cb02aaSDavid Howells pkt.whdr.serial = htonl(serial); 36126cb02aaSDavid Howells 362ed472b0cSDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, sizeof(pkt)); 3632cc80086SDavid Howells ret = do_udp_sendmsg(conn->local->socket, &msg, sizeof(pkt)); 3642cc80086SDavid Howells conn->peer->last_tx_at = ktime_get_seconds(); 3656b47fe1dSDavid Howells if (ret < 0) 3666b47fe1dSDavid Howells trace_rxrpc_tx_fail(call->debug_id, serial, ret, 3674764c0daSDavid Howells rxrpc_tx_point_call_abort); 3684764c0daSDavid Howells else 3694764c0daSDavid Howells trace_rxrpc_tx_packet(call->debug_id, &pkt.whdr, 3704764c0daSDavid Howells rxrpc_tx_point_call_abort); 371c7e86acfSDavid Howells rxrpc_tx_backoff(call, ret); 37226cb02aaSDavid Howells return ret; 37326cb02aaSDavid Howells } 37426cb02aaSDavid Howells 37526cb02aaSDavid Howells /* 3768c3e34a4SDavid Howells * send a packet through the transport endpoint 3778c3e34a4SDavid Howells */ 378a4ea4c47SDavid Howells int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb) 3798c3e34a4SDavid Howells { 3804d843be5SDavid Howells enum rxrpc_req_ack_trace why; 3815a924b89SDavid Howells struct rxrpc_connection *conn = call->conn; 3828c3e34a4SDavid Howells struct msghdr msg; 383a4ea4c47SDavid Howells struct kvec iov[1]; 3845a924b89SDavid Howells rxrpc_serial_t serial; 3855a924b89SDavid Howells size_t len; 3864700c4d8SDavid Howells int ret, rtt_slot = -1; 3878c3e34a4SDavid Howells 388a4ea4c47SDavid Howells _enter("%x,{%d}", txb->seq, txb->len); 3898c3e34a4SDavid Howells 3905a924b89SDavid Howells /* Each transmission of a Tx packet needs a new serial number */ 3915a924b89SDavid Howells serial = atomic_inc_return(&conn->serial); 392a4ea4c47SDavid Howells txb->wire.serial = htonl(serial); 3935a924b89SDavid Howells 3944e255721SDavid Howells if (test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags) && 395a4ea4c47SDavid Howells txb->seq == 1) 396a4ea4c47SDavid Howells txb->wire.userStatus = RXRPC_USERSTATUS_SERVICE_UPGRADE; 3974e255721SDavid Howells 398a4ea4c47SDavid Howells iov[0].iov_base = &txb->wire; 399a4ea4c47SDavid Howells iov[0].iov_len = sizeof(txb->wire) + txb->len; 400a4ea4c47SDavid Howells len = iov[0].iov_len; 401a4ea4c47SDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, len); 4025a924b89SDavid Howells 4035a924b89SDavid Howells msg.msg_name = &call->peer->srx.transport; 4045a924b89SDavid Howells msg.msg_namelen = call->peer->srx.transport_len; 4058c3e34a4SDavid Howells msg.msg_control = NULL; 4068c3e34a4SDavid Howells msg.msg_controllen = 0; 4078c3e34a4SDavid Howells msg.msg_flags = 0; 4088c3e34a4SDavid Howells 40957494343SDavid Howells /* If our RTT cache needs working on, request an ACK. Also request 41057494343SDavid Howells * ACKs if a DATA packet appears to have been lost. 411b604dd98SDavid Howells * 412b604dd98SDavid Howells * However, we mustn't request an ACK on the last reply packet of a 413b604dd98SDavid Howells * service call, lest OpenAFS incorrectly send us an ACK with some 414b604dd98SDavid Howells * soft-ACKs in it and then never follow up with a proper hard ACK. 41557494343SDavid Howells */ 416a4ea4c47SDavid Howells if (txb->wire.flags & RXRPC_REQUEST_ACK) 4174d843be5SDavid Howells why = rxrpc_reqack_already_on; 418a4ea4c47SDavid Howells else if (test_bit(RXRPC_TXBUF_LAST, &txb->flags) && rxrpc_sending_to_client(txb)) 4194d843be5SDavid Howells why = rxrpc_reqack_no_srv_last; 4204d843be5SDavid Howells else if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) 4214d843be5SDavid Howells why = rxrpc_reqack_ack_lost; 422a4ea4c47SDavid Howells else if (test_bit(RXRPC_TXBUF_RESENT, &txb->flags)) 4234d843be5SDavid Howells why = rxrpc_reqack_retrans; 4244d843be5SDavid Howells else if (call->cong_mode == RXRPC_CALL_SLOW_START && call->cong_cwnd <= 2) 4254d843be5SDavid Howells why = rxrpc_reqack_slow_start; 4264d843be5SDavid Howells else if (call->tx_winsize <= 2) 4274d843be5SDavid Howells why = rxrpc_reqack_small_txwin; 428a4ea4c47SDavid Howells else if (call->peer->rtt_count < 3 && txb->seq & 1) 4294d843be5SDavid Howells why = rxrpc_reqack_more_rtt; 4304d843be5SDavid Howells else if (ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), ktime_get_real())) 4314d843be5SDavid Howells why = rxrpc_reqack_old_rtt; 4324d843be5SDavid Howells else 4334d843be5SDavid Howells goto dont_set_request_ack; 4344d843be5SDavid Howells 435f7fa5242SDavid Howells rxrpc_inc_stat(call->rxnet, stat_why_req_ack[why]); 436a4ea4c47SDavid Howells trace_rxrpc_req_ack(call->debug_id, txb->seq, why); 4374d843be5SDavid Howells if (why != rxrpc_reqack_no_srv_last) 438a4ea4c47SDavid Howells txb->wire.flags |= RXRPC_REQUEST_ACK; 4394d843be5SDavid Howells dont_set_request_ack: 4400d4b103cSDavid Howells 4418a681c36SDavid Howells if (IS_ENABLED(CONFIG_AF_RXRPC_INJECT_LOSS)) { 4428a681c36SDavid Howells static int lose; 4438a681c36SDavid Howells if ((lose++ & 7) == 7) { 444a1767077SDavid Howells ret = 0; 445a4ea4c47SDavid Howells trace_rxrpc_tx_data(call, txb->seq, serial, 446a4ea4c47SDavid Howells txb->wire.flags, 447a4ea4c47SDavid Howells test_bit(RXRPC_TXBUF_RESENT, &txb->flags), 448a4ea4c47SDavid Howells true); 449526949e8SArnd Bergmann goto done; 4508a681c36SDavid Howells } 4518a681c36SDavid Howells } 4528a681c36SDavid Howells 453a4ea4c47SDavid Howells trace_rxrpc_tx_data(call, txb->seq, serial, txb->wire.flags, 454a4ea4c47SDavid Howells test_bit(RXRPC_TXBUF_RESENT, &txb->flags), false); 455cf37b598SDavid Howells 456cf37b598SDavid Howells /* Track what we've attempted to transmit at least once so that the 457cf37b598SDavid Howells * retransmission algorithm doesn't try to resend what we haven't sent 458cf37b598SDavid Howells * yet. However, this can race as we can receive an ACK before we get 459cf37b598SDavid Howells * to this point. But, OTOH, if we won't get an ACK mentioning this 460cf37b598SDavid Howells * packet unless the far side received it (though it could have 461cf37b598SDavid Howells * discarded it anyway and NAK'd it). 462cf37b598SDavid Howells */ 463a4ea4c47SDavid Howells cmpxchg(&call->tx_transmitted, txb->seq - 1, txb->seq); 4645a924b89SDavid Howells 4658c3e34a4SDavid Howells /* send the packet with the don't fragment bit set if we currently 4668c3e34a4SDavid Howells * think it's small enough */ 467a4ea4c47SDavid Howells if (txb->len >= call->peer->maxdata) 4685a924b89SDavid Howells goto send_fragmentable; 4695a924b89SDavid Howells 4702cc80086SDavid Howells down_read(&conn->local->defrag_sem); 471b604dd98SDavid Howells 472a4ea4c47SDavid Howells txb->last_sent = ktime_get_real(); 473a4ea4c47SDavid Howells if (txb->wire.flags & RXRPC_REQUEST_ACK) 4744700c4d8SDavid Howells rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_data); 475b604dd98SDavid Howells 4768c3e34a4SDavid Howells /* send the packet by UDP 4778c3e34a4SDavid Howells * - returns -EMSGSIZE if UDP would have to fragment the packet 4788c3e34a4SDavid Howells * to go out of the interface 4798c3e34a4SDavid Howells * - in which case, we'll have processed the ICMP error 4808c3e34a4SDavid Howells * message and update the peer record 4818c3e34a4SDavid Howells */ 482b0154246SDavid Howells rxrpc_inc_stat(call->rxnet, stat_tx_data_send); 4832cc80086SDavid Howells ret = do_udp_sendmsg(conn->local->socket, &msg, len); 4842cc80086SDavid Howells conn->peer->last_tx_at = ktime_get_seconds(); 4858c3e34a4SDavid Howells 4862cc80086SDavid Howells up_read(&conn->local->defrag_sem); 4874700c4d8SDavid Howells if (ret < 0) { 4884700c4d8SDavid Howells rxrpc_cancel_rtt_probe(call, serial, rtt_slot); 4896b47fe1dSDavid Howells trace_rxrpc_tx_fail(call->debug_id, serial, ret, 4904764c0daSDavid Howells rxrpc_tx_point_call_data_nofrag); 4914700c4d8SDavid Howells } else { 492a4ea4c47SDavid Howells trace_rxrpc_tx_packet(call->debug_id, &txb->wire, 4934764c0daSDavid Howells rxrpc_tx_point_call_data_nofrag); 4944700c4d8SDavid Howells } 4954700c4d8SDavid Howells 496c7e86acfSDavid Howells rxrpc_tx_backoff(call, ret); 4978c3e34a4SDavid Howells if (ret == -EMSGSIZE) 4988c3e34a4SDavid Howells goto send_fragmentable; 4998c3e34a4SDavid Howells 5005a924b89SDavid Howells done: 50150235c4bSDavid Howells if (ret >= 0) { 5021fc4fa2aSDavid Howells call->tx_last_sent = txb->last_sent; 503a4ea4c47SDavid Howells if (txb->wire.flags & RXRPC_REQUEST_ACK) { 504a4ea4c47SDavid Howells call->peer->rtt_last_req = txb->last_sent; 505c410bf01SDavid Howells if (call->peer->rtt_count > 1) { 506bd1fdf8cSDavid Howells unsigned long nowj = jiffies, ack_lost_at; 507bd1fdf8cSDavid Howells 5082c13c05cSDavid Howells ack_lost_at = rxrpc_get_rto_backoff(call->peer, false); 509bd1fdf8cSDavid Howells ack_lost_at += nowj; 510bd1fdf8cSDavid Howells WRITE_ONCE(call->ack_lost_at, ack_lost_at); 511bd1fdf8cSDavid Howells rxrpc_reduce_call_timer(call, ack_lost_at, nowj, 512bd1fdf8cSDavid Howells rxrpc_timer_set_for_lost_ack); 513bd1fdf8cSDavid Howells } 5148c3e34a4SDavid Howells } 515c54e43d7SDavid Howells 516a4ea4c47SDavid Howells if (txb->seq == 1 && 517c54e43d7SDavid Howells !test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER, 518c54e43d7SDavid Howells &call->flags)) { 519c54e43d7SDavid Howells unsigned long nowj = jiffies, expect_rx_by; 520c54e43d7SDavid Howells 521c54e43d7SDavid Howells expect_rx_by = nowj + call->next_rx_timo; 522c54e43d7SDavid Howells WRITE_ONCE(call->expect_rx_by, expect_rx_by); 523c54e43d7SDavid Howells rxrpc_reduce_call_timer(call, expect_rx_by, nowj, 524c54e43d7SDavid Howells rxrpc_timer_set_for_normal); 525c54e43d7SDavid Howells } 526415f44e4SDavid Howells 527415f44e4SDavid Howells rxrpc_set_keepalive(call); 528c7e86acfSDavid Howells } else { 529c7e86acfSDavid Howells /* Cancel the call if the initial transmission fails, 530c7e86acfSDavid Howells * particularly if that's due to network routing issues that 531c7e86acfSDavid Howells * aren't going away anytime soon. The layer above can arrange 532c7e86acfSDavid Howells * the retransmission. 533c7e86acfSDavid Howells */ 534c7e86acfSDavid Howells if (!test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER, &call->flags)) 535c7e86acfSDavid Howells rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, 536c7e86acfSDavid Howells RX_USER_ABORT, ret); 537c7e86acfSDavid Howells } 538415f44e4SDavid Howells 5395a924b89SDavid Howells _leave(" = %d [%u]", ret, call->peer->maxdata); 5405a924b89SDavid Howells return ret; 5418c3e34a4SDavid Howells 5428c3e34a4SDavid Howells send_fragmentable: 5438c3e34a4SDavid Howells /* attempt to send this message with fragmentation enabled */ 5448c3e34a4SDavid Howells _debug("send fragment"); 5458c3e34a4SDavid Howells 5462cc80086SDavid Howells down_write(&conn->local->defrag_sem); 547985a5c82SDavid Howells 548a4ea4c47SDavid Howells txb->last_sent = ktime_get_real(); 549a4ea4c47SDavid Howells if (txb->wire.flags & RXRPC_REQUEST_ACK) 5504700c4d8SDavid Howells rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_data); 551b604dd98SDavid Howells 5522cc80086SDavid Howells switch (conn->local->srx.transport.family) { 5530e631eeeSDavid Howells case AF_INET6: 554985a5c82SDavid Howells case AF_INET: 5552cc80086SDavid Howells ip_sock_set_mtu_discover(conn->local->socket->sk, 5562de569bdSChristoph Hellwig IP_PMTUDISC_DONT); 557b0154246SDavid Howells rxrpc_inc_stat(call->rxnet, stat_tx_data_send_frag); 5582cc80086SDavid Howells ret = do_udp_sendmsg(conn->local->socket, &msg, len); 5592cc80086SDavid Howells conn->peer->last_tx_at = ktime_get_seconds(); 5608c3e34a4SDavid Howells 5612cc80086SDavid Howells ip_sock_set_mtu_discover(conn->local->socket->sk, 5622de569bdSChristoph Hellwig IP_PMTUDISC_DO); 56375b54cb5SDavid Howells break; 5643427beb6SDavid Howells 5653427beb6SDavid Howells default: 5663427beb6SDavid Howells BUG(); 5678c3e34a4SDavid Howells } 5688c3e34a4SDavid Howells 5694700c4d8SDavid Howells if (ret < 0) { 5704700c4d8SDavid Howells rxrpc_cancel_rtt_probe(call, serial, rtt_slot); 5716b47fe1dSDavid Howells trace_rxrpc_tx_fail(call->debug_id, serial, ret, 5724764c0daSDavid Howells rxrpc_tx_point_call_data_frag); 5734700c4d8SDavid Howells } else { 574a4ea4c47SDavid Howells trace_rxrpc_tx_packet(call->debug_id, &txb->wire, 5754764c0daSDavid Howells rxrpc_tx_point_call_data_frag); 5764700c4d8SDavid Howells } 577c7e86acfSDavid Howells rxrpc_tx_backoff(call, ret); 5786b47fe1dSDavid Howells 5792cc80086SDavid Howells up_write(&conn->local->defrag_sem); 5805a924b89SDavid Howells goto done; 5818c3e34a4SDavid Howells } 582248f219cSDavid Howells 583248f219cSDavid Howells /* 584*5e6ef4f1SDavid Howells * Reject a packet through the local endpoint. 585248f219cSDavid Howells */ 586*5e6ef4f1SDavid Howells void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb) 587248f219cSDavid Howells { 588248f219cSDavid Howells struct rxrpc_wire_header whdr; 589*5e6ef4f1SDavid Howells struct sockaddr_rxrpc srx; 590*5e6ef4f1SDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 591248f219cSDavid Howells struct msghdr msg; 592248f219cSDavid Howells struct kvec iov[2]; 593248f219cSDavid Howells size_t size; 594248f219cSDavid Howells __be32 code; 595ece64fecSDavid Howells int ret, ioc; 596248f219cSDavid Howells 597*5e6ef4f1SDavid Howells rxrpc_see_skb(skb, rxrpc_skb_see_reject); 598248f219cSDavid Howells 599248f219cSDavid Howells iov[0].iov_base = &whdr; 600248f219cSDavid Howells iov[0].iov_len = sizeof(whdr); 601248f219cSDavid Howells iov[1].iov_base = &code; 602248f219cSDavid Howells iov[1].iov_len = sizeof(code); 603248f219cSDavid Howells 6041c2bc7b9SDavid Howells msg.msg_name = &srx.transport; 605248f219cSDavid Howells msg.msg_control = NULL; 606248f219cSDavid Howells msg.msg_controllen = 0; 607248f219cSDavid Howells msg.msg_flags = 0; 608248f219cSDavid Howells 609248f219cSDavid Howells memset(&whdr, 0, sizeof(whdr)); 610248f219cSDavid Howells 611ece64fecSDavid Howells switch (skb->mark) { 612ece64fecSDavid Howells case RXRPC_SKB_MARK_REJECT_BUSY: 613ece64fecSDavid Howells whdr.type = RXRPC_PACKET_TYPE_BUSY; 614ece64fecSDavid Howells size = sizeof(whdr); 615ece64fecSDavid Howells ioc = 1; 616ece64fecSDavid Howells break; 617ece64fecSDavid Howells case RXRPC_SKB_MARK_REJECT_ABORT: 618ece64fecSDavid Howells whdr.type = RXRPC_PACKET_TYPE_ABORT; 619ece64fecSDavid Howells code = htonl(skb->priority); 620ece64fecSDavid Howells size = sizeof(whdr) + sizeof(code); 621ece64fecSDavid Howells ioc = 2; 622ece64fecSDavid Howells break; 623ece64fecSDavid Howells default: 624*5e6ef4f1SDavid Howells return; 625ece64fecSDavid Howells } 626ece64fecSDavid Howells 6275a790b73SDavid Howells if (rxrpc_extract_addr_from_skb(&srx, skb) == 0) { 6281c2bc7b9SDavid Howells msg.msg_namelen = srx.transport_len; 6291c2bc7b9SDavid Howells 630248f219cSDavid Howells whdr.epoch = htonl(sp->hdr.epoch); 631248f219cSDavid Howells whdr.cid = htonl(sp->hdr.cid); 632248f219cSDavid Howells whdr.callNumber = htonl(sp->hdr.callNumber); 633248f219cSDavid Howells whdr.serviceId = htons(sp->hdr.serviceId); 634248f219cSDavid Howells whdr.flags = sp->hdr.flags; 635248f219cSDavid Howells whdr.flags ^= RXRPC_CLIENT_INITIATED; 636248f219cSDavid Howells whdr.flags &= RXRPC_CLIENT_INITIATED; 637248f219cSDavid Howells 638ed472b0cSDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, ioc, size); 639ed472b0cSDavid Howells ret = do_udp_sendmsg(local->socket, &msg, size); 6406b47fe1dSDavid Howells if (ret < 0) 6416b47fe1dSDavid Howells trace_rxrpc_tx_fail(local->debug_id, 0, ret, 6424764c0daSDavid Howells rxrpc_tx_point_reject); 6434764c0daSDavid Howells else 6444764c0daSDavid Howells trace_rxrpc_tx_packet(local->debug_id, &whdr, 6454764c0daSDavid Howells rxrpc_tx_point_reject); 646248f219cSDavid Howells } 647248f219cSDavid Howells } 648ace45becSDavid Howells 649ace45becSDavid Howells /* 650ace45becSDavid Howells * Send a VERSION reply to a peer as a keepalive. 651ace45becSDavid Howells */ 652ace45becSDavid Howells void rxrpc_send_keepalive(struct rxrpc_peer *peer) 653ace45becSDavid Howells { 654ace45becSDavid Howells struct rxrpc_wire_header whdr; 655ace45becSDavid Howells struct msghdr msg; 656ace45becSDavid Howells struct kvec iov[2]; 657ace45becSDavid Howells size_t len; 658ace45becSDavid Howells int ret; 659ace45becSDavid Howells 660ace45becSDavid Howells _enter(""); 661ace45becSDavid Howells 662ace45becSDavid Howells msg.msg_name = &peer->srx.transport; 663ace45becSDavid Howells msg.msg_namelen = peer->srx.transport_len; 664ace45becSDavid Howells msg.msg_control = NULL; 665ace45becSDavid Howells msg.msg_controllen = 0; 666ace45becSDavid Howells msg.msg_flags = 0; 667ace45becSDavid Howells 668ace45becSDavid Howells whdr.epoch = htonl(peer->local->rxnet->epoch); 669ace45becSDavid Howells whdr.cid = 0; 670ace45becSDavid Howells whdr.callNumber = 0; 671ace45becSDavid Howells whdr.seq = 0; 672ace45becSDavid Howells whdr.serial = 0; 673ace45becSDavid Howells whdr.type = RXRPC_PACKET_TYPE_VERSION; /* Not client-initiated */ 674ace45becSDavid Howells whdr.flags = RXRPC_LAST_PACKET; 675ace45becSDavid Howells whdr.userStatus = 0; 676ace45becSDavid Howells whdr.securityIndex = 0; 677ace45becSDavid Howells whdr._rsvd = 0; 678ace45becSDavid Howells whdr.serviceId = 0; 679ace45becSDavid Howells 680ace45becSDavid Howells iov[0].iov_base = &whdr; 681ace45becSDavid Howells iov[0].iov_len = sizeof(whdr); 682ace45becSDavid Howells iov[1].iov_base = (char *)rxrpc_keepalive_string; 683ace45becSDavid Howells iov[1].iov_len = sizeof(rxrpc_keepalive_string); 684ace45becSDavid Howells 685ace45becSDavid Howells len = iov[0].iov_len + iov[1].iov_len; 686ace45becSDavid Howells 687ed472b0cSDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, 2, len); 688ed472b0cSDavid Howells ret = do_udp_sendmsg(peer->local->socket, &msg, len); 689ace45becSDavid Howells if (ret < 0) 6906b47fe1dSDavid Howells trace_rxrpc_tx_fail(peer->debug_id, 0, ret, 6914764c0daSDavid Howells rxrpc_tx_point_version_keepalive); 6924764c0daSDavid Howells else 6934764c0daSDavid Howells trace_rxrpc_tx_packet(peer->debug_id, &whdr, 6944764c0daSDavid Howells rxrpc_tx_point_version_keepalive); 695ace45becSDavid Howells 696330bdcfaSDavid Howells peer->last_tx_at = ktime_get_seconds(); 697ace45becSDavid Howells _leave(""); 698ace45becSDavid Howells } 699cf37b598SDavid Howells 700cf37b598SDavid Howells /* 701cf37b598SDavid Howells * Schedule an instant Tx resend. 702cf37b598SDavid Howells */ 703cf37b598SDavid Howells static inline void rxrpc_instant_resend(struct rxrpc_call *call, 704cf37b598SDavid Howells struct rxrpc_txbuf *txb) 705cf37b598SDavid Howells { 706cf37b598SDavid Howells if (call->state < RXRPC_CALL_COMPLETE) 707cf37b598SDavid Howells kdebug("resend"); 708cf37b598SDavid Howells } 709cf37b598SDavid Howells 710cf37b598SDavid Howells /* 711cf37b598SDavid Howells * Transmit one packet. 712cf37b598SDavid Howells */ 713cf37b598SDavid Howells void rxrpc_transmit_one(struct rxrpc_call *call, struct rxrpc_txbuf *txb) 714cf37b598SDavid Howells { 715cf37b598SDavid Howells int ret; 716cf37b598SDavid Howells 717cf37b598SDavid Howells ret = rxrpc_send_data_packet(call, txb); 718cf37b598SDavid Howells if (ret < 0) { 719cf37b598SDavid Howells switch (ret) { 720cf37b598SDavid Howells case -ENETUNREACH: 721cf37b598SDavid Howells case -EHOSTUNREACH: 722cf37b598SDavid Howells case -ECONNREFUSED: 723cf37b598SDavid Howells rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, 724cf37b598SDavid Howells 0, ret); 725cf37b598SDavid Howells break; 726cf37b598SDavid Howells default: 727cf37b598SDavid Howells _debug("need instant resend %d", ret); 728cf37b598SDavid Howells rxrpc_instant_resend(call, txb); 729cf37b598SDavid Howells } 730cf37b598SDavid Howells } else { 731cf37b598SDavid Howells unsigned long now = jiffies; 732cf37b598SDavid Howells unsigned long resend_at = now + call->peer->rto_j; 733cf37b598SDavid Howells 734cf37b598SDavid Howells WRITE_ONCE(call->resend_at, resend_at); 735cf37b598SDavid Howells rxrpc_reduce_call_timer(call, resend_at, now, 736cf37b598SDavid Howells rxrpc_timer_set_for_send); 737cf37b598SDavid Howells } 738cf37b598SDavid Howells } 739