162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* RxRPC packet transmission
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/net.h>
1162306a36Sopenharmony_ci#include <linux/gfp.h>
1262306a36Sopenharmony_ci#include <linux/skbuff.h>
1362306a36Sopenharmony_ci#include <linux/export.h>
1462306a36Sopenharmony_ci#include <net/sock.h>
1562306a36Sopenharmony_ci#include <net/af_rxrpc.h>
1662306a36Sopenharmony_ci#include <net/udp.h>
1762306a36Sopenharmony_ci#include "ar-internal.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ciextern int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic ssize_t do_udp_sendmsg(struct socket *socket, struct msghdr *msg, size_t len)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	struct sockaddr *sa = msg->msg_name;
2462306a36Sopenharmony_ci	struct sock *sk = socket->sk;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_AF_RXRPC_IPV6)) {
2762306a36Sopenharmony_ci		if (sa->sa_family == AF_INET6) {
2862306a36Sopenharmony_ci			if (sk->sk_family != AF_INET6) {
2962306a36Sopenharmony_ci				pr_warn("AF_INET6 address on AF_INET socket\n");
3062306a36Sopenharmony_ci				return -ENOPROTOOPT;
3162306a36Sopenharmony_ci			}
3262306a36Sopenharmony_ci			return udpv6_sendmsg(sk, msg, len);
3362306a36Sopenharmony_ci		}
3462306a36Sopenharmony_ci	}
3562306a36Sopenharmony_ci	return udp_sendmsg(sk, msg, len);
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistruct rxrpc_abort_buffer {
3962306a36Sopenharmony_ci	struct rxrpc_wire_header whdr;
4062306a36Sopenharmony_ci	__be32 abort_code;
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic const char rxrpc_keepalive_string[] = "";
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/*
4662306a36Sopenharmony_ci * Increase Tx backoff on transmission failure and clear it on success.
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_cistatic void rxrpc_tx_backoff(struct rxrpc_call *call, int ret)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	if (ret < 0) {
5162306a36Sopenharmony_ci		u16 tx_backoff = READ_ONCE(call->tx_backoff);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci		if (tx_backoff < HZ)
5462306a36Sopenharmony_ci			WRITE_ONCE(call->tx_backoff, tx_backoff + 1);
5562306a36Sopenharmony_ci	} else {
5662306a36Sopenharmony_ci		WRITE_ONCE(call->tx_backoff, 0);
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/*
6162306a36Sopenharmony_ci * Arrange for a keepalive ping a certain time after we last transmitted.  This
6262306a36Sopenharmony_ci * lets the far side know we're still interested in this call and helps keep
6362306a36Sopenharmony_ci * the route through any intervening firewall open.
6462306a36Sopenharmony_ci *
6562306a36Sopenharmony_ci * Receiving a response to the ping will prevent the ->expect_rx_by timer from
6662306a36Sopenharmony_ci * expiring.
6762306a36Sopenharmony_ci */
6862306a36Sopenharmony_cistatic void rxrpc_set_keepalive(struct rxrpc_call *call)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	unsigned long now = jiffies, keepalive_at = call->next_rx_timo / 6;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	keepalive_at += now;
7362306a36Sopenharmony_ci	WRITE_ONCE(call->keepalive_at, keepalive_at);
7462306a36Sopenharmony_ci	rxrpc_reduce_call_timer(call, keepalive_at, now,
7562306a36Sopenharmony_ci				rxrpc_timer_set_for_keepalive);
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/*
7962306a36Sopenharmony_ci * Fill out an ACK packet.
8062306a36Sopenharmony_ci */
8162306a36Sopenharmony_cistatic size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
8262306a36Sopenharmony_ci				 struct rxrpc_call *call,
8362306a36Sopenharmony_ci				 struct rxrpc_txbuf *txb,
8462306a36Sopenharmony_ci				 u16 *_rwind)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	struct rxrpc_ackinfo ackinfo;
8762306a36Sopenharmony_ci	unsigned int qsize, sack, wrap, to;
8862306a36Sopenharmony_ci	rxrpc_seq_t window, wtop;
8962306a36Sopenharmony_ci	int rsize;
9062306a36Sopenharmony_ci	u32 mtu, jmax;
9162306a36Sopenharmony_ci	u8 *ackp = txb->acks;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	call->ackr_nr_unacked = 0;
9462306a36Sopenharmony_ci	atomic_set(&call->ackr_nr_consumed, 0);
9562306a36Sopenharmony_ci	rxrpc_inc_stat(call->rxnet, stat_tx_ack_fill);
9662306a36Sopenharmony_ci	clear_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	window = call->ackr_window;
9962306a36Sopenharmony_ci	wtop   = call->ackr_wtop;
10062306a36Sopenharmony_ci	sack   = call->ackr_sack_base % RXRPC_SACK_SIZE;
10162306a36Sopenharmony_ci	txb->ack.firstPacket = htonl(window);
10262306a36Sopenharmony_ci	txb->ack.nAcks = wtop - window;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	if (after(wtop, window)) {
10562306a36Sopenharmony_ci		wrap = RXRPC_SACK_SIZE - sack;
10662306a36Sopenharmony_ci		to = min_t(unsigned int, txb->ack.nAcks, RXRPC_SACK_SIZE);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci		if (sack + txb->ack.nAcks <= RXRPC_SACK_SIZE) {
10962306a36Sopenharmony_ci			memcpy(txb->acks, call->ackr_sack_table + sack, txb->ack.nAcks);
11062306a36Sopenharmony_ci		} else {
11162306a36Sopenharmony_ci			memcpy(txb->acks, call->ackr_sack_table + sack, wrap);
11262306a36Sopenharmony_ci			memcpy(txb->acks + wrap, call->ackr_sack_table,
11362306a36Sopenharmony_ci			       to - wrap);
11462306a36Sopenharmony_ci		}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci		ackp += to;
11762306a36Sopenharmony_ci	} else if (before(wtop, window)) {
11862306a36Sopenharmony_ci		pr_warn("ack window backward %x %x", window, wtop);
11962306a36Sopenharmony_ci	} else if (txb->ack.reason == RXRPC_ACK_DELAY) {
12062306a36Sopenharmony_ci		txb->ack.reason = RXRPC_ACK_IDLE;
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	mtu = conn->peer->if_mtu;
12462306a36Sopenharmony_ci	mtu -= conn->peer->hdrsize;
12562306a36Sopenharmony_ci	jmax = rxrpc_rx_jumbo_max;
12662306a36Sopenharmony_ci	qsize = (window - 1) - call->rx_consumed;
12762306a36Sopenharmony_ci	rsize = max_t(int, call->rx_winsize - qsize, 0);
12862306a36Sopenharmony_ci	*_rwind = rsize;
12962306a36Sopenharmony_ci	ackinfo.rxMTU		= htonl(rxrpc_rx_mtu);
13062306a36Sopenharmony_ci	ackinfo.maxMTU		= htonl(mtu);
13162306a36Sopenharmony_ci	ackinfo.rwind		= htonl(rsize);
13262306a36Sopenharmony_ci	ackinfo.jumbo_max	= htonl(jmax);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	*ackp++ = 0;
13562306a36Sopenharmony_ci	*ackp++ = 0;
13662306a36Sopenharmony_ci	*ackp++ = 0;
13762306a36Sopenharmony_ci	memcpy(ackp, &ackinfo, sizeof(ackinfo));
13862306a36Sopenharmony_ci	return txb->ack.nAcks + 3 + sizeof(ackinfo);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci/*
14262306a36Sopenharmony_ci * Record the beginning of an RTT probe.
14362306a36Sopenharmony_ci */
14462306a36Sopenharmony_cistatic int rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t serial,
14562306a36Sopenharmony_ci				 enum rxrpc_rtt_tx_trace why)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	unsigned long avail = call->rtt_avail;
14862306a36Sopenharmony_ci	int rtt_slot = 9;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	if (!(avail & RXRPC_CALL_RTT_AVAIL_MASK))
15162306a36Sopenharmony_ci		goto no_slot;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	rtt_slot = __ffs(avail & RXRPC_CALL_RTT_AVAIL_MASK);
15462306a36Sopenharmony_ci	if (!test_and_clear_bit(rtt_slot, &call->rtt_avail))
15562306a36Sopenharmony_ci		goto no_slot;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	call->rtt_serial[rtt_slot] = serial;
15862306a36Sopenharmony_ci	call->rtt_sent_at[rtt_slot] = ktime_get_real();
15962306a36Sopenharmony_ci	smp_wmb(); /* Write data before avail bit */
16062306a36Sopenharmony_ci	set_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	trace_rxrpc_rtt_tx(call, why, rtt_slot, serial);
16362306a36Sopenharmony_ci	return rtt_slot;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cino_slot:
16662306a36Sopenharmony_ci	trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_no_slot, rtt_slot, serial);
16762306a36Sopenharmony_ci	return -1;
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci/*
17162306a36Sopenharmony_ci * Cancel an RTT probe.
17262306a36Sopenharmony_ci */
17362306a36Sopenharmony_cistatic void rxrpc_cancel_rtt_probe(struct rxrpc_call *call,
17462306a36Sopenharmony_ci				   rxrpc_serial_t serial, int rtt_slot)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	if (rtt_slot != -1) {
17762306a36Sopenharmony_ci		clear_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
17862306a36Sopenharmony_ci		smp_wmb(); /* Clear pending bit before setting slot */
17962306a36Sopenharmony_ci		set_bit(rtt_slot, &call->rtt_avail);
18062306a36Sopenharmony_ci		trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_cancel, rtt_slot, serial);
18162306a36Sopenharmony_ci	}
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci/*
18562306a36Sopenharmony_ci * Transmit an ACK packet.
18662306a36Sopenharmony_ci */
18762306a36Sopenharmony_ciint rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci	struct rxrpc_connection *conn;
19062306a36Sopenharmony_ci	struct msghdr msg;
19162306a36Sopenharmony_ci	struct kvec iov[1];
19262306a36Sopenharmony_ci	rxrpc_serial_t serial;
19362306a36Sopenharmony_ci	size_t len, n;
19462306a36Sopenharmony_ci	int ret, rtt_slot = -1;
19562306a36Sopenharmony_ci	u16 rwind;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
19862306a36Sopenharmony_ci		return -ECONNRESET;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	conn = call->conn;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	msg.msg_name	= &call->peer->srx.transport;
20362306a36Sopenharmony_ci	msg.msg_namelen	= call->peer->srx.transport_len;
20462306a36Sopenharmony_ci	msg.msg_control	= NULL;
20562306a36Sopenharmony_ci	msg.msg_controllen = 0;
20662306a36Sopenharmony_ci	msg.msg_flags	= 0;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	if (txb->ack.reason == RXRPC_ACK_PING)
20962306a36Sopenharmony_ci		txb->wire.flags |= RXRPC_REQUEST_ACK;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	n = rxrpc_fill_out_ack(conn, call, txb, &rwind);
21262306a36Sopenharmony_ci	if (n == 0)
21362306a36Sopenharmony_ci		return 0;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	iov[0].iov_base	= &txb->wire;
21662306a36Sopenharmony_ci	iov[0].iov_len	= sizeof(txb->wire) + sizeof(txb->ack) + n;
21762306a36Sopenharmony_ci	len = iov[0].iov_len;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	serial = rxrpc_get_next_serial(conn);
22062306a36Sopenharmony_ci	txb->wire.serial = htonl(serial);
22162306a36Sopenharmony_ci	trace_rxrpc_tx_ack(call->debug_id, serial,
22262306a36Sopenharmony_ci			   ntohl(txb->ack.firstPacket),
22362306a36Sopenharmony_ci			   ntohl(txb->ack.serial), txb->ack.reason, txb->ack.nAcks,
22462306a36Sopenharmony_ci			   rwind);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	if (txb->ack.reason == RXRPC_ACK_PING)
22762306a36Sopenharmony_ci		rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_ping);
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	rxrpc_inc_stat(call->rxnet, stat_tx_ack_send);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	/* Grab the highest received seq as late as possible */
23262306a36Sopenharmony_ci	txb->ack.previousPacket	= htonl(call->rx_highest_seq);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, len);
23562306a36Sopenharmony_ci	ret = do_udp_sendmsg(conn->local->socket, &msg, len);
23662306a36Sopenharmony_ci	call->peer->last_tx_at = ktime_get_seconds();
23762306a36Sopenharmony_ci	if (ret < 0) {
23862306a36Sopenharmony_ci		trace_rxrpc_tx_fail(call->debug_id, serial, ret,
23962306a36Sopenharmony_ci				    rxrpc_tx_point_call_ack);
24062306a36Sopenharmony_ci	} else {
24162306a36Sopenharmony_ci		trace_rxrpc_tx_packet(call->debug_id, &txb->wire,
24262306a36Sopenharmony_ci				      rxrpc_tx_point_call_ack);
24362306a36Sopenharmony_ci		if (txb->wire.flags & RXRPC_REQUEST_ACK)
24462306a36Sopenharmony_ci			call->peer->rtt_last_req = ktime_get_real();
24562306a36Sopenharmony_ci	}
24662306a36Sopenharmony_ci	rxrpc_tx_backoff(call, ret);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	if (!__rxrpc_call_is_complete(call)) {
24962306a36Sopenharmony_ci		if (ret < 0)
25062306a36Sopenharmony_ci			rxrpc_cancel_rtt_probe(call, serial, rtt_slot);
25162306a36Sopenharmony_ci		rxrpc_set_keepalive(call);
25262306a36Sopenharmony_ci	}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	return ret;
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci/*
25862306a36Sopenharmony_ci * Send an ABORT call packet.
25962306a36Sopenharmony_ci */
26062306a36Sopenharmony_ciint rxrpc_send_abort_packet(struct rxrpc_call *call)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	struct rxrpc_connection *conn;
26362306a36Sopenharmony_ci	struct rxrpc_abort_buffer pkt;
26462306a36Sopenharmony_ci	struct msghdr msg;
26562306a36Sopenharmony_ci	struct kvec iov[1];
26662306a36Sopenharmony_ci	rxrpc_serial_t serial;
26762306a36Sopenharmony_ci	int ret;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	/* Don't bother sending aborts for a client call once the server has
27062306a36Sopenharmony_ci	 * hard-ACK'd all of its request data.  After that point, we're not
27162306a36Sopenharmony_ci	 * going to stop the operation proceeding, and whilst we might limit
27262306a36Sopenharmony_ci	 * the reply, it's not worth it if we can send a new call on the same
27362306a36Sopenharmony_ci	 * channel instead, thereby closing off this call.
27462306a36Sopenharmony_ci	 */
27562306a36Sopenharmony_ci	if (rxrpc_is_client_call(call) &&
27662306a36Sopenharmony_ci	    test_bit(RXRPC_CALL_TX_ALL_ACKED, &call->flags))
27762306a36Sopenharmony_ci		return 0;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
28062306a36Sopenharmony_ci		return -ECONNRESET;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	conn = call->conn;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	msg.msg_name	= &call->peer->srx.transport;
28562306a36Sopenharmony_ci	msg.msg_namelen	= call->peer->srx.transport_len;
28662306a36Sopenharmony_ci	msg.msg_control	= NULL;
28762306a36Sopenharmony_ci	msg.msg_controllen = 0;
28862306a36Sopenharmony_ci	msg.msg_flags	= 0;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	pkt.whdr.epoch		= htonl(conn->proto.epoch);
29162306a36Sopenharmony_ci	pkt.whdr.cid		= htonl(call->cid);
29262306a36Sopenharmony_ci	pkt.whdr.callNumber	= htonl(call->call_id);
29362306a36Sopenharmony_ci	pkt.whdr.seq		= 0;
29462306a36Sopenharmony_ci	pkt.whdr.type		= RXRPC_PACKET_TYPE_ABORT;
29562306a36Sopenharmony_ci	pkt.whdr.flags		= conn->out_clientflag;
29662306a36Sopenharmony_ci	pkt.whdr.userStatus	= 0;
29762306a36Sopenharmony_ci	pkt.whdr.securityIndex	= call->security_ix;
29862306a36Sopenharmony_ci	pkt.whdr._rsvd		= 0;
29962306a36Sopenharmony_ci	pkt.whdr.serviceId	= htons(call->dest_srx.srx_service);
30062306a36Sopenharmony_ci	pkt.abort_code		= htonl(call->abort_code);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	iov[0].iov_base	= &pkt;
30362306a36Sopenharmony_ci	iov[0].iov_len	= sizeof(pkt);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	serial = rxrpc_get_next_serial(conn);
30662306a36Sopenharmony_ci	pkt.whdr.serial = htonl(serial);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, sizeof(pkt));
30962306a36Sopenharmony_ci	ret = do_udp_sendmsg(conn->local->socket, &msg, sizeof(pkt));
31062306a36Sopenharmony_ci	conn->peer->last_tx_at = ktime_get_seconds();
31162306a36Sopenharmony_ci	if (ret < 0)
31262306a36Sopenharmony_ci		trace_rxrpc_tx_fail(call->debug_id, serial, ret,
31362306a36Sopenharmony_ci				    rxrpc_tx_point_call_abort);
31462306a36Sopenharmony_ci	else
31562306a36Sopenharmony_ci		trace_rxrpc_tx_packet(call->debug_id, &pkt.whdr,
31662306a36Sopenharmony_ci				      rxrpc_tx_point_call_abort);
31762306a36Sopenharmony_ci	rxrpc_tx_backoff(call, ret);
31862306a36Sopenharmony_ci	return ret;
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci/*
32262306a36Sopenharmony_ci * send a packet through the transport endpoint
32362306a36Sopenharmony_ci */
32462306a36Sopenharmony_ciint rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	enum rxrpc_req_ack_trace why;
32762306a36Sopenharmony_ci	struct rxrpc_connection *conn = call->conn;
32862306a36Sopenharmony_ci	struct msghdr msg;
32962306a36Sopenharmony_ci	struct kvec iov[1];
33062306a36Sopenharmony_ci	rxrpc_serial_t serial;
33162306a36Sopenharmony_ci	size_t len;
33262306a36Sopenharmony_ci	int ret, rtt_slot = -1;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	_enter("%x,{%d}", txb->seq, txb->len);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	/* Each transmission of a Tx packet needs a new serial number */
33762306a36Sopenharmony_ci	serial = rxrpc_get_next_serial(conn);
33862306a36Sopenharmony_ci	txb->wire.serial = htonl(serial);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	if (test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags) &&
34162306a36Sopenharmony_ci	    txb->seq == 1)
34262306a36Sopenharmony_ci		txb->wire.userStatus = RXRPC_USERSTATUS_SERVICE_UPGRADE;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	iov[0].iov_base = &txb->wire;
34562306a36Sopenharmony_ci	iov[0].iov_len = sizeof(txb->wire) + txb->len;
34662306a36Sopenharmony_ci	len = iov[0].iov_len;
34762306a36Sopenharmony_ci	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, len);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	msg.msg_name = &call->peer->srx.transport;
35062306a36Sopenharmony_ci	msg.msg_namelen = call->peer->srx.transport_len;
35162306a36Sopenharmony_ci	msg.msg_control = NULL;
35262306a36Sopenharmony_ci	msg.msg_controllen = 0;
35362306a36Sopenharmony_ci	msg.msg_flags = 0;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	/* If our RTT cache needs working on, request an ACK.  Also request
35662306a36Sopenharmony_ci	 * ACKs if a DATA packet appears to have been lost.
35762306a36Sopenharmony_ci	 *
35862306a36Sopenharmony_ci	 * However, we mustn't request an ACK on the last reply packet of a
35962306a36Sopenharmony_ci	 * service call, lest OpenAFS incorrectly send us an ACK with some
36062306a36Sopenharmony_ci	 * soft-ACKs in it and then never follow up with a proper hard ACK.
36162306a36Sopenharmony_ci	 */
36262306a36Sopenharmony_ci	if (txb->wire.flags & RXRPC_REQUEST_ACK)
36362306a36Sopenharmony_ci		why = rxrpc_reqack_already_on;
36462306a36Sopenharmony_ci	else if (test_bit(RXRPC_TXBUF_LAST, &txb->flags) && rxrpc_sending_to_client(txb))
36562306a36Sopenharmony_ci		why = rxrpc_reqack_no_srv_last;
36662306a36Sopenharmony_ci	else if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events))
36762306a36Sopenharmony_ci		why = rxrpc_reqack_ack_lost;
36862306a36Sopenharmony_ci	else if (test_bit(RXRPC_TXBUF_RESENT, &txb->flags))
36962306a36Sopenharmony_ci		why = rxrpc_reqack_retrans;
37062306a36Sopenharmony_ci	else if (call->cong_mode == RXRPC_CALL_SLOW_START && call->cong_cwnd <= 2)
37162306a36Sopenharmony_ci		why = rxrpc_reqack_slow_start;
37262306a36Sopenharmony_ci	else if (call->tx_winsize <= 2)
37362306a36Sopenharmony_ci		why = rxrpc_reqack_small_txwin;
37462306a36Sopenharmony_ci	else if (call->peer->rtt_count < 3 && txb->seq & 1)
37562306a36Sopenharmony_ci		why = rxrpc_reqack_more_rtt;
37662306a36Sopenharmony_ci	else if (ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), ktime_get_real()))
37762306a36Sopenharmony_ci		why = rxrpc_reqack_old_rtt;
37862306a36Sopenharmony_ci	else
37962306a36Sopenharmony_ci		goto dont_set_request_ack;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	rxrpc_inc_stat(call->rxnet, stat_why_req_ack[why]);
38262306a36Sopenharmony_ci	trace_rxrpc_req_ack(call->debug_id, txb->seq, why);
38362306a36Sopenharmony_ci	if (why != rxrpc_reqack_no_srv_last)
38462306a36Sopenharmony_ci		txb->wire.flags |= RXRPC_REQUEST_ACK;
38562306a36Sopenharmony_cidont_set_request_ack:
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_AF_RXRPC_INJECT_LOSS)) {
38862306a36Sopenharmony_ci		static int lose;
38962306a36Sopenharmony_ci		if ((lose++ & 7) == 7) {
39062306a36Sopenharmony_ci			ret = 0;
39162306a36Sopenharmony_ci			trace_rxrpc_tx_data(call, txb->seq, serial,
39262306a36Sopenharmony_ci					    txb->wire.flags,
39362306a36Sopenharmony_ci					    test_bit(RXRPC_TXBUF_RESENT, &txb->flags),
39462306a36Sopenharmony_ci					    true);
39562306a36Sopenharmony_ci			goto done;
39662306a36Sopenharmony_ci		}
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	trace_rxrpc_tx_data(call, txb->seq, serial, txb->wire.flags,
40062306a36Sopenharmony_ci			    test_bit(RXRPC_TXBUF_RESENT, &txb->flags), false);
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	/* Track what we've attempted to transmit at least once so that the
40362306a36Sopenharmony_ci	 * retransmission algorithm doesn't try to resend what we haven't sent
40462306a36Sopenharmony_ci	 * yet.  However, this can race as we can receive an ACK before we get
40562306a36Sopenharmony_ci	 * to this point.  But, OTOH, if we won't get an ACK mentioning this
40662306a36Sopenharmony_ci	 * packet unless the far side received it (though it could have
40762306a36Sopenharmony_ci	 * discarded it anyway and NAK'd it).
40862306a36Sopenharmony_ci	 */
40962306a36Sopenharmony_ci	cmpxchg(&call->tx_transmitted, txb->seq - 1, txb->seq);
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	/* send the packet with the don't fragment bit set if we currently
41262306a36Sopenharmony_ci	 * think it's small enough */
41362306a36Sopenharmony_ci	if (txb->len >= call->peer->maxdata)
41462306a36Sopenharmony_ci		goto send_fragmentable;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	txb->last_sent = ktime_get_real();
41762306a36Sopenharmony_ci	if (txb->wire.flags & RXRPC_REQUEST_ACK)
41862306a36Sopenharmony_ci		rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_data);
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	/* send the packet by UDP
42162306a36Sopenharmony_ci	 * - returns -EMSGSIZE if UDP would have to fragment the packet
42262306a36Sopenharmony_ci	 *   to go out of the interface
42362306a36Sopenharmony_ci	 *   - in which case, we'll have processed the ICMP error
42462306a36Sopenharmony_ci	 *     message and update the peer record
42562306a36Sopenharmony_ci	 */
42662306a36Sopenharmony_ci	rxrpc_inc_stat(call->rxnet, stat_tx_data_send);
42762306a36Sopenharmony_ci	ret = do_udp_sendmsg(conn->local->socket, &msg, len);
42862306a36Sopenharmony_ci	conn->peer->last_tx_at = ktime_get_seconds();
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	if (ret < 0) {
43162306a36Sopenharmony_ci		rxrpc_inc_stat(call->rxnet, stat_tx_data_send_fail);
43262306a36Sopenharmony_ci		rxrpc_cancel_rtt_probe(call, serial, rtt_slot);
43362306a36Sopenharmony_ci		trace_rxrpc_tx_fail(call->debug_id, serial, ret,
43462306a36Sopenharmony_ci				    rxrpc_tx_point_call_data_nofrag);
43562306a36Sopenharmony_ci	} else {
43662306a36Sopenharmony_ci		trace_rxrpc_tx_packet(call->debug_id, &txb->wire,
43762306a36Sopenharmony_ci				      rxrpc_tx_point_call_data_nofrag);
43862306a36Sopenharmony_ci	}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	rxrpc_tx_backoff(call, ret);
44162306a36Sopenharmony_ci	if (ret == -EMSGSIZE)
44262306a36Sopenharmony_ci		goto send_fragmentable;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_cidone:
44562306a36Sopenharmony_ci	if (ret >= 0) {
44662306a36Sopenharmony_ci		call->tx_last_sent = txb->last_sent;
44762306a36Sopenharmony_ci		if (txb->wire.flags & RXRPC_REQUEST_ACK) {
44862306a36Sopenharmony_ci			call->peer->rtt_last_req = txb->last_sent;
44962306a36Sopenharmony_ci			if (call->peer->rtt_count > 1) {
45062306a36Sopenharmony_ci				unsigned long nowj = jiffies, ack_lost_at;
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci				ack_lost_at = rxrpc_get_rto_backoff(call->peer, false);
45362306a36Sopenharmony_ci				ack_lost_at += nowj;
45462306a36Sopenharmony_ci				WRITE_ONCE(call->ack_lost_at, ack_lost_at);
45562306a36Sopenharmony_ci				rxrpc_reduce_call_timer(call, ack_lost_at, nowj,
45662306a36Sopenharmony_ci							rxrpc_timer_set_for_lost_ack);
45762306a36Sopenharmony_ci			}
45862306a36Sopenharmony_ci		}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci		if (txb->seq == 1 &&
46162306a36Sopenharmony_ci		    !test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER,
46262306a36Sopenharmony_ci				      &call->flags)) {
46362306a36Sopenharmony_ci			unsigned long nowj = jiffies, expect_rx_by;
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci			expect_rx_by = nowj + call->next_rx_timo;
46662306a36Sopenharmony_ci			WRITE_ONCE(call->expect_rx_by, expect_rx_by);
46762306a36Sopenharmony_ci			rxrpc_reduce_call_timer(call, expect_rx_by, nowj,
46862306a36Sopenharmony_ci						rxrpc_timer_set_for_normal);
46962306a36Sopenharmony_ci		}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci		rxrpc_set_keepalive(call);
47262306a36Sopenharmony_ci	} else {
47362306a36Sopenharmony_ci		/* Cancel the call if the initial transmission fails,
47462306a36Sopenharmony_ci		 * particularly if that's due to network routing issues that
47562306a36Sopenharmony_ci		 * aren't going away anytime soon.  The layer above can arrange
47662306a36Sopenharmony_ci		 * the retransmission.
47762306a36Sopenharmony_ci		 */
47862306a36Sopenharmony_ci		if (!test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER, &call->flags))
47962306a36Sopenharmony_ci			rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
48062306a36Sopenharmony_ci						  RX_USER_ABORT, ret);
48162306a36Sopenharmony_ci	}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	_leave(" = %d [%u]", ret, call->peer->maxdata);
48462306a36Sopenharmony_ci	return ret;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_cisend_fragmentable:
48762306a36Sopenharmony_ci	/* attempt to send this message with fragmentation enabled */
48862306a36Sopenharmony_ci	_debug("send fragment");
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	txb->last_sent = ktime_get_real();
49162306a36Sopenharmony_ci	if (txb->wire.flags & RXRPC_REQUEST_ACK)
49262306a36Sopenharmony_ci		rtt_slot = rxrpc_begin_rtt_probe(call, serial, rxrpc_rtt_tx_data);
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	switch (conn->local->srx.transport.family) {
49562306a36Sopenharmony_ci	case AF_INET6:
49662306a36Sopenharmony_ci	case AF_INET:
49762306a36Sopenharmony_ci		rxrpc_local_dont_fragment(conn->local, false);
49862306a36Sopenharmony_ci		rxrpc_inc_stat(call->rxnet, stat_tx_data_send_frag);
49962306a36Sopenharmony_ci		ret = do_udp_sendmsg(conn->local->socket, &msg, len);
50062306a36Sopenharmony_ci		conn->peer->last_tx_at = ktime_get_seconds();
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci		rxrpc_local_dont_fragment(conn->local, true);
50362306a36Sopenharmony_ci		break;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	default:
50662306a36Sopenharmony_ci		BUG();
50762306a36Sopenharmony_ci	}
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	if (ret < 0) {
51062306a36Sopenharmony_ci		rxrpc_inc_stat(call->rxnet, stat_tx_data_send_fail);
51162306a36Sopenharmony_ci		rxrpc_cancel_rtt_probe(call, serial, rtt_slot);
51262306a36Sopenharmony_ci		trace_rxrpc_tx_fail(call->debug_id, serial, ret,
51362306a36Sopenharmony_ci				    rxrpc_tx_point_call_data_frag);
51462306a36Sopenharmony_ci	} else {
51562306a36Sopenharmony_ci		trace_rxrpc_tx_packet(call->debug_id, &txb->wire,
51662306a36Sopenharmony_ci				      rxrpc_tx_point_call_data_frag);
51762306a36Sopenharmony_ci	}
51862306a36Sopenharmony_ci	rxrpc_tx_backoff(call, ret);
51962306a36Sopenharmony_ci	goto done;
52062306a36Sopenharmony_ci}
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci/*
52362306a36Sopenharmony_ci * Transmit a connection-level abort.
52462306a36Sopenharmony_ci */
52562306a36Sopenharmony_civoid rxrpc_send_conn_abort(struct rxrpc_connection *conn)
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	struct rxrpc_wire_header whdr;
52862306a36Sopenharmony_ci	struct msghdr msg;
52962306a36Sopenharmony_ci	struct kvec iov[2];
53062306a36Sopenharmony_ci	__be32 word;
53162306a36Sopenharmony_ci	size_t len;
53262306a36Sopenharmony_ci	u32 serial;
53362306a36Sopenharmony_ci	int ret;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	msg.msg_name	= &conn->peer->srx.transport;
53662306a36Sopenharmony_ci	msg.msg_namelen	= conn->peer->srx.transport_len;
53762306a36Sopenharmony_ci	msg.msg_control	= NULL;
53862306a36Sopenharmony_ci	msg.msg_controllen = 0;
53962306a36Sopenharmony_ci	msg.msg_flags	= 0;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	whdr.epoch	= htonl(conn->proto.epoch);
54262306a36Sopenharmony_ci	whdr.cid	= htonl(conn->proto.cid);
54362306a36Sopenharmony_ci	whdr.callNumber	= 0;
54462306a36Sopenharmony_ci	whdr.seq	= 0;
54562306a36Sopenharmony_ci	whdr.type	= RXRPC_PACKET_TYPE_ABORT;
54662306a36Sopenharmony_ci	whdr.flags	= conn->out_clientflag;
54762306a36Sopenharmony_ci	whdr.userStatus	= 0;
54862306a36Sopenharmony_ci	whdr.securityIndex = conn->security_ix;
54962306a36Sopenharmony_ci	whdr._rsvd	= 0;
55062306a36Sopenharmony_ci	whdr.serviceId	= htons(conn->service_id);
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	word		= htonl(conn->abort_code);
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	iov[0].iov_base	= &whdr;
55562306a36Sopenharmony_ci	iov[0].iov_len	= sizeof(whdr);
55662306a36Sopenharmony_ci	iov[1].iov_base	= &word;
55762306a36Sopenharmony_ci	iov[1].iov_len	= sizeof(word);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	len = iov[0].iov_len + iov[1].iov_len;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	serial = rxrpc_get_next_serial(conn);
56262306a36Sopenharmony_ci	whdr.serial = htonl(serial);
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 2, len);
56562306a36Sopenharmony_ci	ret = do_udp_sendmsg(conn->local->socket, &msg, len);
56662306a36Sopenharmony_ci	if (ret < 0) {
56762306a36Sopenharmony_ci		trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
56862306a36Sopenharmony_ci				    rxrpc_tx_point_conn_abort);
56962306a36Sopenharmony_ci		_debug("sendmsg failed: %d", ret);
57062306a36Sopenharmony_ci		return;
57162306a36Sopenharmony_ci	}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	trace_rxrpc_tx_packet(conn->debug_id, &whdr, rxrpc_tx_point_conn_abort);
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	conn->peer->last_tx_at = ktime_get_seconds();
57662306a36Sopenharmony_ci}
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci/*
57962306a36Sopenharmony_ci * Reject a packet through the local endpoint.
58062306a36Sopenharmony_ci */
58162306a36Sopenharmony_civoid rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	struct rxrpc_wire_header whdr;
58462306a36Sopenharmony_ci	struct sockaddr_rxrpc srx;
58562306a36Sopenharmony_ci	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
58662306a36Sopenharmony_ci	struct msghdr msg;
58762306a36Sopenharmony_ci	struct kvec iov[2];
58862306a36Sopenharmony_ci	size_t size;
58962306a36Sopenharmony_ci	__be32 code;
59062306a36Sopenharmony_ci	int ret, ioc;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	rxrpc_see_skb(skb, rxrpc_skb_see_reject);
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	iov[0].iov_base = &whdr;
59562306a36Sopenharmony_ci	iov[0].iov_len = sizeof(whdr);
59662306a36Sopenharmony_ci	iov[1].iov_base = &code;
59762306a36Sopenharmony_ci	iov[1].iov_len = sizeof(code);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	msg.msg_name = &srx.transport;
60062306a36Sopenharmony_ci	msg.msg_control = NULL;
60162306a36Sopenharmony_ci	msg.msg_controllen = 0;
60262306a36Sopenharmony_ci	msg.msg_flags = 0;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	memset(&whdr, 0, sizeof(whdr));
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	switch (skb->mark) {
60762306a36Sopenharmony_ci	case RXRPC_SKB_MARK_REJECT_BUSY:
60862306a36Sopenharmony_ci		whdr.type = RXRPC_PACKET_TYPE_BUSY;
60962306a36Sopenharmony_ci		size = sizeof(whdr);
61062306a36Sopenharmony_ci		ioc = 1;
61162306a36Sopenharmony_ci		break;
61262306a36Sopenharmony_ci	case RXRPC_SKB_MARK_REJECT_ABORT:
61362306a36Sopenharmony_ci		whdr.type = RXRPC_PACKET_TYPE_ABORT;
61462306a36Sopenharmony_ci		code = htonl(skb->priority);
61562306a36Sopenharmony_ci		size = sizeof(whdr) + sizeof(code);
61662306a36Sopenharmony_ci		ioc = 2;
61762306a36Sopenharmony_ci		break;
61862306a36Sopenharmony_ci	default:
61962306a36Sopenharmony_ci		return;
62062306a36Sopenharmony_ci	}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	if (rxrpc_extract_addr_from_skb(&srx, skb) == 0) {
62362306a36Sopenharmony_ci		msg.msg_namelen = srx.transport_len;
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci		whdr.epoch	= htonl(sp->hdr.epoch);
62662306a36Sopenharmony_ci		whdr.cid	= htonl(sp->hdr.cid);
62762306a36Sopenharmony_ci		whdr.callNumber	= htonl(sp->hdr.callNumber);
62862306a36Sopenharmony_ci		whdr.serviceId	= htons(sp->hdr.serviceId);
62962306a36Sopenharmony_ci		whdr.flags	= sp->hdr.flags;
63062306a36Sopenharmony_ci		whdr.flags	^= RXRPC_CLIENT_INITIATED;
63162306a36Sopenharmony_ci		whdr.flags	&= RXRPC_CLIENT_INITIATED;
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci		iov_iter_kvec(&msg.msg_iter, WRITE, iov, ioc, size);
63462306a36Sopenharmony_ci		ret = do_udp_sendmsg(local->socket, &msg, size);
63562306a36Sopenharmony_ci		if (ret < 0)
63662306a36Sopenharmony_ci			trace_rxrpc_tx_fail(local->debug_id, 0, ret,
63762306a36Sopenharmony_ci					    rxrpc_tx_point_reject);
63862306a36Sopenharmony_ci		else
63962306a36Sopenharmony_ci			trace_rxrpc_tx_packet(local->debug_id, &whdr,
64062306a36Sopenharmony_ci					      rxrpc_tx_point_reject);
64162306a36Sopenharmony_ci	}
64262306a36Sopenharmony_ci}
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci/*
64562306a36Sopenharmony_ci * Send a VERSION reply to a peer as a keepalive.
64662306a36Sopenharmony_ci */
64762306a36Sopenharmony_civoid rxrpc_send_keepalive(struct rxrpc_peer *peer)
64862306a36Sopenharmony_ci{
64962306a36Sopenharmony_ci	struct rxrpc_wire_header whdr;
65062306a36Sopenharmony_ci	struct msghdr msg;
65162306a36Sopenharmony_ci	struct kvec iov[2];
65262306a36Sopenharmony_ci	size_t len;
65362306a36Sopenharmony_ci	int ret;
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	_enter("");
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	msg.msg_name	= &peer->srx.transport;
65862306a36Sopenharmony_ci	msg.msg_namelen	= peer->srx.transport_len;
65962306a36Sopenharmony_ci	msg.msg_control	= NULL;
66062306a36Sopenharmony_ci	msg.msg_controllen = 0;
66162306a36Sopenharmony_ci	msg.msg_flags	= 0;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	whdr.epoch	= htonl(peer->local->rxnet->epoch);
66462306a36Sopenharmony_ci	whdr.cid	= 0;
66562306a36Sopenharmony_ci	whdr.callNumber	= 0;
66662306a36Sopenharmony_ci	whdr.seq	= 0;
66762306a36Sopenharmony_ci	whdr.serial	= 0;
66862306a36Sopenharmony_ci	whdr.type	= RXRPC_PACKET_TYPE_VERSION; /* Not client-initiated */
66962306a36Sopenharmony_ci	whdr.flags	= RXRPC_LAST_PACKET;
67062306a36Sopenharmony_ci	whdr.userStatus	= 0;
67162306a36Sopenharmony_ci	whdr.securityIndex = 0;
67262306a36Sopenharmony_ci	whdr._rsvd	= 0;
67362306a36Sopenharmony_ci	whdr.serviceId	= 0;
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	iov[0].iov_base	= &whdr;
67662306a36Sopenharmony_ci	iov[0].iov_len	= sizeof(whdr);
67762306a36Sopenharmony_ci	iov[1].iov_base	= (char *)rxrpc_keepalive_string;
67862306a36Sopenharmony_ci	iov[1].iov_len	= sizeof(rxrpc_keepalive_string);
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	len = iov[0].iov_len + iov[1].iov_len;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 2, len);
68362306a36Sopenharmony_ci	ret = do_udp_sendmsg(peer->local->socket, &msg, len);
68462306a36Sopenharmony_ci	if (ret < 0)
68562306a36Sopenharmony_ci		trace_rxrpc_tx_fail(peer->debug_id, 0, ret,
68662306a36Sopenharmony_ci				    rxrpc_tx_point_version_keepalive);
68762306a36Sopenharmony_ci	else
68862306a36Sopenharmony_ci		trace_rxrpc_tx_packet(peer->debug_id, &whdr,
68962306a36Sopenharmony_ci				      rxrpc_tx_point_version_keepalive);
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	peer->last_tx_at = ktime_get_seconds();
69262306a36Sopenharmony_ci	_leave("");
69362306a36Sopenharmony_ci}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci/*
69662306a36Sopenharmony_ci * Schedule an instant Tx resend.
69762306a36Sopenharmony_ci */
69862306a36Sopenharmony_cistatic inline void rxrpc_instant_resend(struct rxrpc_call *call,
69962306a36Sopenharmony_ci					struct rxrpc_txbuf *txb)
70062306a36Sopenharmony_ci{
70162306a36Sopenharmony_ci	if (!__rxrpc_call_is_complete(call))
70262306a36Sopenharmony_ci		kdebug("resend");
70362306a36Sopenharmony_ci}
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci/*
70662306a36Sopenharmony_ci * Transmit one packet.
70762306a36Sopenharmony_ci */
70862306a36Sopenharmony_civoid rxrpc_transmit_one(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
70962306a36Sopenharmony_ci{
71062306a36Sopenharmony_ci	int ret;
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	ret = rxrpc_send_data_packet(call, txb);
71362306a36Sopenharmony_ci	if (ret < 0) {
71462306a36Sopenharmony_ci		switch (ret) {
71562306a36Sopenharmony_ci		case -ENETUNREACH:
71662306a36Sopenharmony_ci		case -EHOSTUNREACH:
71762306a36Sopenharmony_ci		case -ECONNREFUSED:
71862306a36Sopenharmony_ci			rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
71962306a36Sopenharmony_ci						  0, ret);
72062306a36Sopenharmony_ci			break;
72162306a36Sopenharmony_ci		default:
72262306a36Sopenharmony_ci			_debug("need instant resend %d", ret);
72362306a36Sopenharmony_ci			rxrpc_instant_resend(call, txb);
72462306a36Sopenharmony_ci		}
72562306a36Sopenharmony_ci	} else {
72662306a36Sopenharmony_ci		unsigned long now = jiffies;
72762306a36Sopenharmony_ci		unsigned long resend_at = now + call->peer->rto_j;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci		WRITE_ONCE(call->resend_at, resend_at);
73062306a36Sopenharmony_ci		rxrpc_reduce_call_timer(call, resend_at, now,
73162306a36Sopenharmony_ci					rxrpc_timer_set_for_send);
73262306a36Sopenharmony_ci	}
73362306a36Sopenharmony_ci}
734