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 /* 206b0346843SDavid Howells * Transmit an ACK packet. 2078d94aa38SDavid Howells */ 208b0346843SDavid Howells int rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb) 2098d94aa38SDavid Howells { 2105273a191SDavid Howells struct rxrpc_connection *conn; 2118d94aa38SDavid Howells struct msghdr msg; 21272f0c6fbSDavid Howells struct kvec iov[1]; 2138d94aa38SDavid Howells rxrpc_serial_t serial; 2148d94aa38SDavid Howells size_t len, n; 2154700c4d8SDavid Howells int ret, rtt_slot = -1; 2168d94aa38SDavid Howells 2175273a191SDavid Howells if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) 2188d94aa38SDavid Howells return -ECONNRESET; 2198d94aa38SDavid Howells 2205273a191SDavid Howells conn = call->conn; 2218d94aa38SDavid Howells 2228d94aa38SDavid Howells msg.msg_name = &call->peer->srx.transport; 2238d94aa38SDavid Howells msg.msg_namelen = call->peer->srx.transport_len; 2248d94aa38SDavid Howells msg.msg_control = NULL; 2258d94aa38SDavid Howells msg.msg_controllen = 0; 2268d94aa38SDavid Howells msg.msg_flags = 0; 2278d94aa38SDavid Howells 22872f0c6fbSDavid Howells if (txb->ack.reason == RXRPC_ACK_PING) 22972f0c6fbSDavid Howells txb->wire.flags |= RXRPC_REQUEST_ACK; 2308d94aa38SDavid Howells 2315d7edbc9SDavid Howells n = rxrpc_fill_out_ack(conn, call, txb); 2324e76bd40SDavid Howells if (n == 0) 2339a3dedcfSDavid Howells return 0; 2348d94aa38SDavid Howells 23572f0c6fbSDavid Howells iov[0].iov_base = &txb->wire; 23672f0c6fbSDavid Howells iov[0].iov_len = sizeof(txb->wire) + sizeof(txb->ack) + n; 23772f0c6fbSDavid Howells len = iov[0].iov_len; 2388d94aa38SDavid Howells 239b86e218eSDavid Howells serial = atomic_inc_return(&conn->serial); 24072f0c6fbSDavid Howells txb->wire.serial = htonl(serial); 2414764c0daSDavid Howells trace_rxrpc_tx_ack(call->debug_id, serial, 24272f0c6fbSDavid Howells ntohl(txb->ack.firstPacket), 24372f0c6fbSDavid Howells ntohl(txb->ack.serial), txb->ack.reason, txb->ack.nAcks); 244b86e218eSDavid Howells 24572f0c6fbSDavid Howells if (txb->ack.reason == RXRPC_ACK_PING) 2464700c4d8SDavid Howells rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_ping); 24726cb02aaSDavid Howells 248f2a676d1SDavid Howells rxrpc_inc_stat(call->rxnet, stat_tx_ack_send); 249ed472b0cSDavid Howells 2505d7edbc9SDavid Howells /* Grab the highest received seq as late as possible */ 2515d7edbc9SDavid Howells txb->ack.previousPacket = htonl(call->rx_highest_seq); 2525d7edbc9SDavid Howells 25372f0c6fbSDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, len); 2542cc80086SDavid Howells ret = do_udp_sendmsg(conn->local->socket, &msg, len); 255ed472b0cSDavid Howells call->peer->last_tx_at = ktime_get_seconds(); 256*84e28aa5SDavid Howells if (ret < 0) { 2576b47fe1dSDavid Howells trace_rxrpc_tx_fail(call->debug_id, serial, ret, 2584764c0daSDavid Howells rxrpc_tx_point_call_ack); 259*84e28aa5SDavid Howells } else { 26072f0c6fbSDavid Howells trace_rxrpc_tx_packet(call->debug_id, &txb->wire, 2614764c0daSDavid Howells rxrpc_tx_point_call_ack); 262*84e28aa5SDavid Howells if (txb->wire.flags & RXRPC_REQUEST_ACK) 263*84e28aa5SDavid Howells call->peer->rtt_last_req = ktime_get_real(); 264*84e28aa5SDavid Howells } 265c7e86acfSDavid Howells rxrpc_tx_backoff(call, ret); 2668d94aa38SDavid Howells 26796b4059fSDavid Howells if (!__rxrpc_call_is_complete(call)) { 26872f0c6fbSDavid Howells if (ret < 0) 2694700c4d8SDavid Howells rxrpc_cancel_rtt_probe(call, serial, rtt_slot); 270415f44e4SDavid Howells rxrpc_set_keepalive(call); 271248f219cSDavid Howells } 272248f219cSDavid Howells 2738d94aa38SDavid Howells return ret; 2748d94aa38SDavid Howells } 2758d94aa38SDavid Howells 2768c3e34a4SDavid Howells /* 27726cb02aaSDavid Howells * Send an ABORT call packet. 27826cb02aaSDavid Howells */ 27926cb02aaSDavid Howells int rxrpc_send_abort_packet(struct rxrpc_call *call) 28026cb02aaSDavid Howells { 2815273a191SDavid Howells struct rxrpc_connection *conn; 28226cb02aaSDavid Howells struct rxrpc_abort_buffer pkt; 28326cb02aaSDavid Howells struct msghdr msg; 28426cb02aaSDavid Howells struct kvec iov[1]; 28526cb02aaSDavid Howells rxrpc_serial_t serial; 28626cb02aaSDavid Howells int ret; 28726cb02aaSDavid Howells 288dcbefc30SDavid Howells /* Don't bother sending aborts for a client call once the server has 289dcbefc30SDavid Howells * hard-ACK'd all of its request data. After that point, we're not 290dcbefc30SDavid Howells * going to stop the operation proceeding, and whilst we might limit 291dcbefc30SDavid Howells * the reply, it's not worth it if we can send a new call on the same 292dcbefc30SDavid Howells * channel instead, thereby closing off this call. 293dcbefc30SDavid Howells */ 294dcbefc30SDavid Howells if (rxrpc_is_client_call(call) && 295a4ea4c47SDavid Howells test_bit(RXRPC_CALL_TX_ALL_ACKED, &call->flags)) 296dcbefc30SDavid Howells return 0; 297dcbefc30SDavid Howells 2985273a191SDavid Howells if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) 29926cb02aaSDavid Howells return -ECONNRESET; 30026cb02aaSDavid Howells 3015273a191SDavid Howells conn = call->conn; 3025273a191SDavid Howells 30326cb02aaSDavid Howells msg.msg_name = &call->peer->srx.transport; 30426cb02aaSDavid Howells msg.msg_namelen = call->peer->srx.transport_len; 30526cb02aaSDavid Howells msg.msg_control = NULL; 30626cb02aaSDavid Howells msg.msg_controllen = 0; 30726cb02aaSDavid Howells msg.msg_flags = 0; 30826cb02aaSDavid Howells 30926cb02aaSDavid Howells pkt.whdr.epoch = htonl(conn->proto.epoch); 31026cb02aaSDavid Howells pkt.whdr.cid = htonl(call->cid); 31126cb02aaSDavid Howells pkt.whdr.callNumber = htonl(call->call_id); 31226cb02aaSDavid Howells pkt.whdr.seq = 0; 31326cb02aaSDavid Howells pkt.whdr.type = RXRPC_PACKET_TYPE_ABORT; 31426cb02aaSDavid Howells pkt.whdr.flags = conn->out_clientflag; 31526cb02aaSDavid Howells pkt.whdr.userStatus = 0; 31626cb02aaSDavid Howells pkt.whdr.securityIndex = call->security_ix; 31726cb02aaSDavid Howells pkt.whdr._rsvd = 0; 318f3441d41SDavid Howells pkt.whdr.serviceId = htons(call->dest_srx.srx_service); 31926cb02aaSDavid Howells pkt.abort_code = htonl(call->abort_code); 32026cb02aaSDavid Howells 32126cb02aaSDavid Howells iov[0].iov_base = &pkt; 32226cb02aaSDavid Howells iov[0].iov_len = sizeof(pkt); 32326cb02aaSDavid Howells 32426cb02aaSDavid Howells serial = atomic_inc_return(&conn->serial); 32526cb02aaSDavid Howells pkt.whdr.serial = htonl(serial); 32626cb02aaSDavid Howells 327ed472b0cSDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, sizeof(pkt)); 3282cc80086SDavid Howells ret = do_udp_sendmsg(conn->local->socket, &msg, sizeof(pkt)); 3292cc80086SDavid Howells conn->peer->last_tx_at = ktime_get_seconds(); 3306b47fe1dSDavid Howells if (ret < 0) 3316b47fe1dSDavid Howells trace_rxrpc_tx_fail(call->debug_id, serial, ret, 3324764c0daSDavid Howells rxrpc_tx_point_call_abort); 3334764c0daSDavid Howells else 3344764c0daSDavid Howells trace_rxrpc_tx_packet(call->debug_id, &pkt.whdr, 3354764c0daSDavid Howells rxrpc_tx_point_call_abort); 336c7e86acfSDavid Howells rxrpc_tx_backoff(call, ret); 33726cb02aaSDavid Howells return ret; 33826cb02aaSDavid Howells } 33926cb02aaSDavid Howells 34026cb02aaSDavid Howells /* 3418c3e34a4SDavid Howells * send a packet through the transport endpoint 3428c3e34a4SDavid Howells */ 343a4ea4c47SDavid Howells int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb) 3448c3e34a4SDavid Howells { 3454d843be5SDavid Howells enum rxrpc_req_ack_trace why; 3465a924b89SDavid Howells struct rxrpc_connection *conn = call->conn; 3478c3e34a4SDavid Howells struct msghdr msg; 348a4ea4c47SDavid Howells struct kvec iov[1]; 3495a924b89SDavid Howells rxrpc_serial_t serial; 3505a924b89SDavid Howells size_t len; 3514700c4d8SDavid Howells int ret, rtt_slot = -1; 3528c3e34a4SDavid Howells 353a4ea4c47SDavid Howells _enter("%x,{%d}", txb->seq, txb->len); 3548c3e34a4SDavid Howells 3555a924b89SDavid Howells /* Each transmission of a Tx packet needs a new serial number */ 3565a924b89SDavid Howells serial = atomic_inc_return(&conn->serial); 357a4ea4c47SDavid Howells txb->wire.serial = htonl(serial); 3585a924b89SDavid Howells 3594e255721SDavid Howells if (test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags) && 360a4ea4c47SDavid Howells txb->seq == 1) 361a4ea4c47SDavid Howells txb->wire.userStatus = RXRPC_USERSTATUS_SERVICE_UPGRADE; 3624e255721SDavid Howells 363a4ea4c47SDavid Howells iov[0].iov_base = &txb->wire; 364a4ea4c47SDavid Howells iov[0].iov_len = sizeof(txb->wire) + txb->len; 365a4ea4c47SDavid Howells len = iov[0].iov_len; 366a4ea4c47SDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, len); 3675a924b89SDavid Howells 3685a924b89SDavid Howells msg.msg_name = &call->peer->srx.transport; 3695a924b89SDavid Howells msg.msg_namelen = call->peer->srx.transport_len; 3708c3e34a4SDavid Howells msg.msg_control = NULL; 3718c3e34a4SDavid Howells msg.msg_controllen = 0; 3728c3e34a4SDavid Howells msg.msg_flags = 0; 3738c3e34a4SDavid Howells 37457494343SDavid Howells /* If our RTT cache needs working on, request an ACK. Also request 37557494343SDavid Howells * ACKs if a DATA packet appears to have been lost. 376b604dd98SDavid Howells * 377b604dd98SDavid Howells * However, we mustn't request an ACK on the last reply packet of a 378b604dd98SDavid Howells * service call, lest OpenAFS incorrectly send us an ACK with some 379b604dd98SDavid Howells * soft-ACKs in it and then never follow up with a proper hard ACK. 38057494343SDavid Howells */ 381a4ea4c47SDavid Howells if (txb->wire.flags & RXRPC_REQUEST_ACK) 3824d843be5SDavid Howells why = rxrpc_reqack_already_on; 383a4ea4c47SDavid Howells else if (test_bit(RXRPC_TXBUF_LAST, &txb->flags) && rxrpc_sending_to_client(txb)) 3844d843be5SDavid Howells why = rxrpc_reqack_no_srv_last; 3854d843be5SDavid Howells else if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) 3864d843be5SDavid Howells why = rxrpc_reqack_ack_lost; 387a4ea4c47SDavid Howells else if (test_bit(RXRPC_TXBUF_RESENT, &txb->flags)) 3884d843be5SDavid Howells why = rxrpc_reqack_retrans; 3894d843be5SDavid Howells else if (call->cong_mode == RXRPC_CALL_SLOW_START && call->cong_cwnd <= 2) 3904d843be5SDavid Howells why = rxrpc_reqack_slow_start; 3914d843be5SDavid Howells else if (call->tx_winsize <= 2) 3924d843be5SDavid Howells why = rxrpc_reqack_small_txwin; 393a4ea4c47SDavid Howells else if (call->peer->rtt_count < 3 && txb->seq & 1) 3944d843be5SDavid Howells why = rxrpc_reqack_more_rtt; 3954d843be5SDavid Howells else if (ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), ktime_get_real())) 3964d843be5SDavid Howells why = rxrpc_reqack_old_rtt; 3974d843be5SDavid Howells else 3984d843be5SDavid Howells goto dont_set_request_ack; 3994d843be5SDavid Howells 400f7fa5242SDavid Howells rxrpc_inc_stat(call->rxnet, stat_why_req_ack[why]); 401a4ea4c47SDavid Howells trace_rxrpc_req_ack(call->debug_id, txb->seq, why); 4024d843be5SDavid Howells if (why != rxrpc_reqack_no_srv_last) 403a4ea4c47SDavid Howells txb->wire.flags |= RXRPC_REQUEST_ACK; 4044d843be5SDavid Howells dont_set_request_ack: 4050d4b103cSDavid Howells 4068a681c36SDavid Howells if (IS_ENABLED(CONFIG_AF_RXRPC_INJECT_LOSS)) { 4078a681c36SDavid Howells static int lose; 4088a681c36SDavid Howells if ((lose++ & 7) == 7) { 409a1767077SDavid Howells ret = 0; 410a4ea4c47SDavid Howells trace_rxrpc_tx_data(call, txb->seq, serial, 411a4ea4c47SDavid Howells txb->wire.flags, 412a4ea4c47SDavid Howells test_bit(RXRPC_TXBUF_RESENT, &txb->flags), 413a4ea4c47SDavid Howells true); 414526949e8SArnd Bergmann goto done; 4158a681c36SDavid Howells } 4168a681c36SDavid Howells } 4178a681c36SDavid Howells 418a4ea4c47SDavid Howells trace_rxrpc_tx_data(call, txb->seq, serial, txb->wire.flags, 419a4ea4c47SDavid Howells test_bit(RXRPC_TXBUF_RESENT, &txb->flags), false); 420cf37b598SDavid Howells 421cf37b598SDavid Howells /* Track what we've attempted to transmit at least once so that the 422cf37b598SDavid Howells * retransmission algorithm doesn't try to resend what we haven't sent 423cf37b598SDavid Howells * yet. However, this can race as we can receive an ACK before we get 424cf37b598SDavid Howells * to this point. But, OTOH, if we won't get an ACK mentioning this 425cf37b598SDavid Howells * packet unless the far side received it (though it could have 426cf37b598SDavid Howells * discarded it anyway and NAK'd it). 427cf37b598SDavid Howells */ 428a4ea4c47SDavid Howells cmpxchg(&call->tx_transmitted, txb->seq - 1, txb->seq); 4295a924b89SDavid Howells 4308c3e34a4SDavid Howells /* send the packet with the don't fragment bit set if we currently 4318c3e34a4SDavid Howells * think it's small enough */ 432a4ea4c47SDavid Howells if (txb->len >= call->peer->maxdata) 4335a924b89SDavid Howells goto send_fragmentable; 4345a924b89SDavid Howells 4352cc80086SDavid Howells down_read(&conn->local->defrag_sem); 436b604dd98SDavid Howells 437a4ea4c47SDavid Howells txb->last_sent = ktime_get_real(); 438a4ea4c47SDavid Howells if (txb->wire.flags & RXRPC_REQUEST_ACK) 4394700c4d8SDavid Howells rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_data); 440b604dd98SDavid Howells 4418c3e34a4SDavid Howells /* send the packet by UDP 4428c3e34a4SDavid Howells * - returns -EMSGSIZE if UDP would have to fragment the packet 4438c3e34a4SDavid Howells * to go out of the interface 4448c3e34a4SDavid Howells * - in which case, we'll have processed the ICMP error 4458c3e34a4SDavid Howells * message and update the peer record 4468c3e34a4SDavid Howells */ 447b0154246SDavid Howells rxrpc_inc_stat(call->rxnet, stat_tx_data_send); 4482cc80086SDavid Howells ret = do_udp_sendmsg(conn->local->socket, &msg, len); 4492cc80086SDavid Howells conn->peer->last_tx_at = ktime_get_seconds(); 4508c3e34a4SDavid Howells 4512cc80086SDavid Howells up_read(&conn->local->defrag_sem); 4524700c4d8SDavid Howells if (ret < 0) { 45332cf8edbSDavid Howells rxrpc_inc_stat(call->rxnet, stat_tx_data_send_fail); 4544700c4d8SDavid Howells rxrpc_cancel_rtt_probe(call, serial, rtt_slot); 4556b47fe1dSDavid Howells trace_rxrpc_tx_fail(call->debug_id, serial, ret, 4564764c0daSDavid Howells rxrpc_tx_point_call_data_nofrag); 4574700c4d8SDavid Howells } else { 458a4ea4c47SDavid Howells trace_rxrpc_tx_packet(call->debug_id, &txb->wire, 4594764c0daSDavid Howells rxrpc_tx_point_call_data_nofrag); 4604700c4d8SDavid Howells } 4614700c4d8SDavid Howells 462c7e86acfSDavid Howells rxrpc_tx_backoff(call, ret); 4638c3e34a4SDavid Howells if (ret == -EMSGSIZE) 4648c3e34a4SDavid Howells goto send_fragmentable; 4658c3e34a4SDavid Howells 4665a924b89SDavid Howells done: 46750235c4bSDavid Howells if (ret >= 0) { 4681fc4fa2aSDavid Howells call->tx_last_sent = txb->last_sent; 469a4ea4c47SDavid Howells if (txb->wire.flags & RXRPC_REQUEST_ACK) { 470a4ea4c47SDavid Howells call->peer->rtt_last_req = txb->last_sent; 471c410bf01SDavid Howells if (call->peer->rtt_count > 1) { 472bd1fdf8cSDavid Howells unsigned long nowj = jiffies, ack_lost_at; 473bd1fdf8cSDavid Howells 4742c13c05cSDavid Howells ack_lost_at = rxrpc_get_rto_backoff(call->peer, false); 475bd1fdf8cSDavid Howells ack_lost_at += nowj; 476bd1fdf8cSDavid Howells WRITE_ONCE(call->ack_lost_at, ack_lost_at); 477bd1fdf8cSDavid Howells rxrpc_reduce_call_timer(call, ack_lost_at, nowj, 478bd1fdf8cSDavid Howells rxrpc_timer_set_for_lost_ack); 479bd1fdf8cSDavid Howells } 4808c3e34a4SDavid Howells } 481c54e43d7SDavid Howells 482a4ea4c47SDavid Howells if (txb->seq == 1 && 483c54e43d7SDavid Howells !test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER, 484c54e43d7SDavid Howells &call->flags)) { 485c54e43d7SDavid Howells unsigned long nowj = jiffies, expect_rx_by; 486c54e43d7SDavid Howells 487c54e43d7SDavid Howells expect_rx_by = nowj + call->next_rx_timo; 488c54e43d7SDavid Howells WRITE_ONCE(call->expect_rx_by, expect_rx_by); 489c54e43d7SDavid Howells rxrpc_reduce_call_timer(call, expect_rx_by, nowj, 490c54e43d7SDavid Howells rxrpc_timer_set_for_normal); 491c54e43d7SDavid Howells } 492415f44e4SDavid Howells 493415f44e4SDavid Howells rxrpc_set_keepalive(call); 494c7e86acfSDavid Howells } else { 495c7e86acfSDavid Howells /* Cancel the call if the initial transmission fails, 496c7e86acfSDavid Howells * particularly if that's due to network routing issues that 497c7e86acfSDavid Howells * aren't going away anytime soon. The layer above can arrange 498c7e86acfSDavid Howells * the retransmission. 499c7e86acfSDavid Howells */ 500c7e86acfSDavid Howells if (!test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER, &call->flags)) 501c7e86acfSDavid Howells rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, 502c7e86acfSDavid Howells RX_USER_ABORT, ret); 503c7e86acfSDavid Howells } 504415f44e4SDavid Howells 5055a924b89SDavid Howells _leave(" = %d [%u]", ret, call->peer->maxdata); 5065a924b89SDavid Howells return ret; 5078c3e34a4SDavid Howells 5088c3e34a4SDavid Howells send_fragmentable: 5098c3e34a4SDavid Howells /* attempt to send this message with fragmentation enabled */ 5108c3e34a4SDavid Howells _debug("send fragment"); 5118c3e34a4SDavid Howells 5122cc80086SDavid Howells down_write(&conn->local->defrag_sem); 513985a5c82SDavid Howells 514a4ea4c47SDavid Howells txb->last_sent = ktime_get_real(); 515a4ea4c47SDavid Howells if (txb->wire.flags & RXRPC_REQUEST_ACK) 5164700c4d8SDavid Howells rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_data); 517b604dd98SDavid Howells 5182cc80086SDavid Howells switch (conn->local->srx.transport.family) { 5190e631eeeSDavid Howells case AF_INET6: 520985a5c82SDavid Howells case AF_INET: 5212cc80086SDavid Howells ip_sock_set_mtu_discover(conn->local->socket->sk, 5222de569bdSChristoph Hellwig IP_PMTUDISC_DONT); 523b0154246SDavid Howells rxrpc_inc_stat(call->rxnet, stat_tx_data_send_frag); 5242cc80086SDavid Howells ret = do_udp_sendmsg(conn->local->socket, &msg, len); 5252cc80086SDavid Howells conn->peer->last_tx_at = ktime_get_seconds(); 5268c3e34a4SDavid Howells 5272cc80086SDavid Howells ip_sock_set_mtu_discover(conn->local->socket->sk, 5282de569bdSChristoph Hellwig IP_PMTUDISC_DO); 52975b54cb5SDavid Howells break; 5303427beb6SDavid Howells 5313427beb6SDavid Howells default: 5323427beb6SDavid Howells BUG(); 5338c3e34a4SDavid Howells } 5348c3e34a4SDavid Howells 5354700c4d8SDavid Howells if (ret < 0) { 53632cf8edbSDavid Howells rxrpc_inc_stat(call->rxnet, stat_tx_data_send_fail); 5374700c4d8SDavid Howells rxrpc_cancel_rtt_probe(call, serial, rtt_slot); 5386b47fe1dSDavid Howells trace_rxrpc_tx_fail(call->debug_id, serial, ret, 5394764c0daSDavid Howells rxrpc_tx_point_call_data_frag); 5404700c4d8SDavid Howells } else { 541a4ea4c47SDavid Howells trace_rxrpc_tx_packet(call->debug_id, &txb->wire, 5424764c0daSDavid Howells rxrpc_tx_point_call_data_frag); 5434700c4d8SDavid Howells } 544c7e86acfSDavid Howells rxrpc_tx_backoff(call, ret); 5456b47fe1dSDavid Howells 5462cc80086SDavid Howells up_write(&conn->local->defrag_sem); 5475a924b89SDavid Howells goto done; 5488c3e34a4SDavid Howells } 549248f219cSDavid Howells 550248f219cSDavid Howells /* 551a00ce28bSDavid Howells * Transmit a connection-level abort. 552a00ce28bSDavid Howells */ 553a00ce28bSDavid Howells void rxrpc_send_conn_abort(struct rxrpc_connection *conn) 554a00ce28bSDavid Howells { 555a00ce28bSDavid Howells struct rxrpc_wire_header whdr; 556a00ce28bSDavid Howells struct msghdr msg; 557a00ce28bSDavid Howells struct kvec iov[2]; 558a00ce28bSDavid Howells __be32 word; 559a00ce28bSDavid Howells size_t len; 560a00ce28bSDavid Howells u32 serial; 561a00ce28bSDavid Howells int ret; 562a00ce28bSDavid Howells 563a00ce28bSDavid Howells msg.msg_name = &conn->peer->srx.transport; 564a00ce28bSDavid Howells msg.msg_namelen = conn->peer->srx.transport_len; 565a00ce28bSDavid Howells msg.msg_control = NULL; 566a00ce28bSDavid Howells msg.msg_controllen = 0; 567a00ce28bSDavid Howells msg.msg_flags = 0; 568a00ce28bSDavid Howells 569a00ce28bSDavid Howells whdr.epoch = htonl(conn->proto.epoch); 570a00ce28bSDavid Howells whdr.cid = htonl(conn->proto.cid); 571a00ce28bSDavid Howells whdr.callNumber = 0; 572a00ce28bSDavid Howells whdr.seq = 0; 573a00ce28bSDavid Howells whdr.type = RXRPC_PACKET_TYPE_ABORT; 574a00ce28bSDavid Howells whdr.flags = conn->out_clientflag; 575a00ce28bSDavid Howells whdr.userStatus = 0; 576a00ce28bSDavid Howells whdr.securityIndex = conn->security_ix; 577a00ce28bSDavid Howells whdr._rsvd = 0; 578a00ce28bSDavid Howells whdr.serviceId = htons(conn->service_id); 579a00ce28bSDavid Howells 580a00ce28bSDavid Howells word = htonl(conn->abort_code); 581a00ce28bSDavid Howells 582a00ce28bSDavid Howells iov[0].iov_base = &whdr; 583a00ce28bSDavid Howells iov[0].iov_len = sizeof(whdr); 584a00ce28bSDavid Howells iov[1].iov_base = &word; 585a00ce28bSDavid Howells iov[1].iov_len = sizeof(word); 586a00ce28bSDavid Howells 587a00ce28bSDavid Howells len = iov[0].iov_len + iov[1].iov_len; 588a00ce28bSDavid Howells 589a00ce28bSDavid Howells serial = atomic_inc_return(&conn->serial); 590a00ce28bSDavid Howells whdr.serial = htonl(serial); 591a00ce28bSDavid Howells 592a00ce28bSDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, 2, len); 593a00ce28bSDavid Howells ret = do_udp_sendmsg(conn->local->socket, &msg, len); 594a00ce28bSDavid Howells if (ret < 0) { 595a00ce28bSDavid Howells trace_rxrpc_tx_fail(conn->debug_id, serial, ret, 596a00ce28bSDavid Howells rxrpc_tx_point_conn_abort); 597a00ce28bSDavid Howells _debug("sendmsg failed: %d", ret); 598a00ce28bSDavid Howells return; 599a00ce28bSDavid Howells } 600a00ce28bSDavid Howells 601a00ce28bSDavid Howells trace_rxrpc_tx_packet(conn->debug_id, &whdr, rxrpc_tx_point_conn_abort); 602a00ce28bSDavid Howells 603a00ce28bSDavid Howells conn->peer->last_tx_at = ktime_get_seconds(); 604a00ce28bSDavid Howells } 605a00ce28bSDavid Howells 606a00ce28bSDavid Howells /* 6075e6ef4f1SDavid Howells * Reject a packet through the local endpoint. 608248f219cSDavid Howells */ 6095e6ef4f1SDavid Howells void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb) 610248f219cSDavid Howells { 611248f219cSDavid Howells struct rxrpc_wire_header whdr; 6125e6ef4f1SDavid Howells struct sockaddr_rxrpc srx; 6135e6ef4f1SDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 614248f219cSDavid Howells struct msghdr msg; 615248f219cSDavid Howells struct kvec iov[2]; 616248f219cSDavid Howells size_t size; 617248f219cSDavid Howells __be32 code; 618ece64fecSDavid Howells int ret, ioc; 619248f219cSDavid Howells 6205e6ef4f1SDavid Howells rxrpc_see_skb(skb, rxrpc_skb_see_reject); 621248f219cSDavid Howells 622248f219cSDavid Howells iov[0].iov_base = &whdr; 623248f219cSDavid Howells iov[0].iov_len = sizeof(whdr); 624248f219cSDavid Howells iov[1].iov_base = &code; 625248f219cSDavid Howells iov[1].iov_len = sizeof(code); 626248f219cSDavid Howells 6271c2bc7b9SDavid Howells msg.msg_name = &srx.transport; 628248f219cSDavid Howells msg.msg_control = NULL; 629248f219cSDavid Howells msg.msg_controllen = 0; 630248f219cSDavid Howells msg.msg_flags = 0; 631248f219cSDavid Howells 632248f219cSDavid Howells memset(&whdr, 0, sizeof(whdr)); 633248f219cSDavid Howells 634ece64fecSDavid Howells switch (skb->mark) { 635ece64fecSDavid Howells case RXRPC_SKB_MARK_REJECT_BUSY: 636ece64fecSDavid Howells whdr.type = RXRPC_PACKET_TYPE_BUSY; 637ece64fecSDavid Howells size = sizeof(whdr); 638ece64fecSDavid Howells ioc = 1; 639ece64fecSDavid Howells break; 640ece64fecSDavid Howells case RXRPC_SKB_MARK_REJECT_ABORT: 641ece64fecSDavid Howells whdr.type = RXRPC_PACKET_TYPE_ABORT; 642ece64fecSDavid Howells code = htonl(skb->priority); 643ece64fecSDavid Howells size = sizeof(whdr) + sizeof(code); 644ece64fecSDavid Howells ioc = 2; 645ece64fecSDavid Howells break; 646ece64fecSDavid Howells default: 6475e6ef4f1SDavid Howells return; 648ece64fecSDavid Howells } 649ece64fecSDavid Howells 6505a790b73SDavid Howells if (rxrpc_extract_addr_from_skb(&srx, skb) == 0) { 6511c2bc7b9SDavid Howells msg.msg_namelen = srx.transport_len; 6521c2bc7b9SDavid Howells 653248f219cSDavid Howells whdr.epoch = htonl(sp->hdr.epoch); 654248f219cSDavid Howells whdr.cid = htonl(sp->hdr.cid); 655248f219cSDavid Howells whdr.callNumber = htonl(sp->hdr.callNumber); 656248f219cSDavid Howells whdr.serviceId = htons(sp->hdr.serviceId); 657248f219cSDavid Howells whdr.flags = sp->hdr.flags; 658248f219cSDavid Howells whdr.flags ^= RXRPC_CLIENT_INITIATED; 659248f219cSDavid Howells whdr.flags &= RXRPC_CLIENT_INITIATED; 660248f219cSDavid Howells 661ed472b0cSDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, ioc, size); 662ed472b0cSDavid Howells ret = do_udp_sendmsg(local->socket, &msg, size); 6636b47fe1dSDavid Howells if (ret < 0) 6646b47fe1dSDavid Howells trace_rxrpc_tx_fail(local->debug_id, 0, ret, 6654764c0daSDavid Howells rxrpc_tx_point_reject); 6664764c0daSDavid Howells else 6674764c0daSDavid Howells trace_rxrpc_tx_packet(local->debug_id, &whdr, 6684764c0daSDavid Howells rxrpc_tx_point_reject); 669248f219cSDavid Howells } 670248f219cSDavid Howells } 671ace45becSDavid Howells 672ace45becSDavid Howells /* 673ace45becSDavid Howells * Send a VERSION reply to a peer as a keepalive. 674ace45becSDavid Howells */ 675ace45becSDavid Howells void rxrpc_send_keepalive(struct rxrpc_peer *peer) 676ace45becSDavid Howells { 677ace45becSDavid Howells struct rxrpc_wire_header whdr; 678ace45becSDavid Howells struct msghdr msg; 679ace45becSDavid Howells struct kvec iov[2]; 680ace45becSDavid Howells size_t len; 681ace45becSDavid Howells int ret; 682ace45becSDavid Howells 683ace45becSDavid Howells _enter(""); 684ace45becSDavid Howells 685ace45becSDavid Howells msg.msg_name = &peer->srx.transport; 686ace45becSDavid Howells msg.msg_namelen = peer->srx.transport_len; 687ace45becSDavid Howells msg.msg_control = NULL; 688ace45becSDavid Howells msg.msg_controllen = 0; 689ace45becSDavid Howells msg.msg_flags = 0; 690ace45becSDavid Howells 691ace45becSDavid Howells whdr.epoch = htonl(peer->local->rxnet->epoch); 692ace45becSDavid Howells whdr.cid = 0; 693ace45becSDavid Howells whdr.callNumber = 0; 694ace45becSDavid Howells whdr.seq = 0; 695ace45becSDavid Howells whdr.serial = 0; 696ace45becSDavid Howells whdr.type = RXRPC_PACKET_TYPE_VERSION; /* Not client-initiated */ 697ace45becSDavid Howells whdr.flags = RXRPC_LAST_PACKET; 698ace45becSDavid Howells whdr.userStatus = 0; 699ace45becSDavid Howells whdr.securityIndex = 0; 700ace45becSDavid Howells whdr._rsvd = 0; 701ace45becSDavid Howells whdr.serviceId = 0; 702ace45becSDavid Howells 703ace45becSDavid Howells iov[0].iov_base = &whdr; 704ace45becSDavid Howells iov[0].iov_len = sizeof(whdr); 705ace45becSDavid Howells iov[1].iov_base = (char *)rxrpc_keepalive_string; 706ace45becSDavid Howells iov[1].iov_len = sizeof(rxrpc_keepalive_string); 707ace45becSDavid Howells 708ace45becSDavid Howells len = iov[0].iov_len + iov[1].iov_len; 709ace45becSDavid Howells 710ed472b0cSDavid Howells iov_iter_kvec(&msg.msg_iter, WRITE, iov, 2, len); 711ed472b0cSDavid Howells ret = do_udp_sendmsg(peer->local->socket, &msg, len); 712ace45becSDavid Howells if (ret < 0) 7136b47fe1dSDavid Howells trace_rxrpc_tx_fail(peer->debug_id, 0, ret, 7144764c0daSDavid Howells rxrpc_tx_point_version_keepalive); 7154764c0daSDavid Howells else 7164764c0daSDavid Howells trace_rxrpc_tx_packet(peer->debug_id, &whdr, 7174764c0daSDavid Howells rxrpc_tx_point_version_keepalive); 718ace45becSDavid Howells 719330bdcfaSDavid Howells peer->last_tx_at = ktime_get_seconds(); 720ace45becSDavid Howells _leave(""); 721ace45becSDavid Howells } 722cf37b598SDavid Howells 723cf37b598SDavid Howells /* 724cf37b598SDavid Howells * Schedule an instant Tx resend. 725cf37b598SDavid Howells */ 726cf37b598SDavid Howells static inline void rxrpc_instant_resend(struct rxrpc_call *call, 727cf37b598SDavid Howells struct rxrpc_txbuf *txb) 728cf37b598SDavid Howells { 72996b4059fSDavid Howells if (!__rxrpc_call_is_complete(call)) 730cf37b598SDavid Howells kdebug("resend"); 731cf37b598SDavid Howells } 732cf37b598SDavid Howells 733cf37b598SDavid Howells /* 734cf37b598SDavid Howells * Transmit one packet. 735cf37b598SDavid Howells */ 736cf37b598SDavid Howells void rxrpc_transmit_one(struct rxrpc_call *call, struct rxrpc_txbuf *txb) 737cf37b598SDavid Howells { 738cf37b598SDavid Howells int ret; 739cf37b598SDavid Howells 740cf37b598SDavid Howells ret = rxrpc_send_data_packet(call, txb); 741cf37b598SDavid Howells if (ret < 0) { 742cf37b598SDavid Howells switch (ret) { 743cf37b598SDavid Howells case -ENETUNREACH: 744cf37b598SDavid Howells case -EHOSTUNREACH: 745cf37b598SDavid Howells case -ECONNREFUSED: 746cf37b598SDavid Howells rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, 747cf37b598SDavid Howells 0, ret); 748cf37b598SDavid Howells break; 749cf37b598SDavid Howells default: 750cf37b598SDavid Howells _debug("need instant resend %d", ret); 751cf37b598SDavid Howells rxrpc_instant_resend(call, txb); 752cf37b598SDavid Howells } 753cf37b598SDavid Howells } else { 754cf37b598SDavid Howells unsigned long now = jiffies; 755cf37b598SDavid Howells unsigned long resend_at = now + call->peer->rto_j; 756cf37b598SDavid Howells 757cf37b598SDavid Howells WRITE_ONCE(call->resend_at, resend_at); 758cf37b598SDavid Howells rxrpc_reduce_call_timer(call, resend_at, now, 759cf37b598SDavid Howells rxrpc_timer_set_for_send); 760cf37b598SDavid Howells } 761cf37b598SDavid Howells } 762