162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* Management of Tx window, Tx resend, ACKs and out-of-sequence reception
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/module.h>
1162306a36Sopenharmony_ci#include <linux/circ_buf.h>
1262306a36Sopenharmony_ci#include <linux/net.h>
1362306a36Sopenharmony_ci#include <linux/skbuff.h>
1462306a36Sopenharmony_ci#include <linux/slab.h>
1562306a36Sopenharmony_ci#include <linux/udp.h>
1662306a36Sopenharmony_ci#include <net/sock.h>
1762306a36Sopenharmony_ci#include <net/af_rxrpc.h>
1862306a36Sopenharmony_ci#include "ar-internal.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * Propose a PING ACK be sent.
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_civoid rxrpc_propose_ping(struct rxrpc_call *call, u32 serial,
2462306a36Sopenharmony_ci			enum rxrpc_propose_ack_trace why)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	unsigned long now = jiffies;
2762306a36Sopenharmony_ci	unsigned long ping_at = now + rxrpc_idle_ack_delay;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	if (time_before(ping_at, call->ping_at)) {
3062306a36Sopenharmony_ci		WRITE_ONCE(call->ping_at, ping_at);
3162306a36Sopenharmony_ci		rxrpc_reduce_call_timer(call, ping_at, now,
3262306a36Sopenharmony_ci					rxrpc_timer_set_for_ping);
3362306a36Sopenharmony_ci		trace_rxrpc_propose_ack(call, why, RXRPC_ACK_PING, serial);
3462306a36Sopenharmony_ci	}
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/*
3862306a36Sopenharmony_ci * Propose a DELAY ACK be sent in the future.
3962306a36Sopenharmony_ci */
4062306a36Sopenharmony_civoid rxrpc_propose_delay_ACK(struct rxrpc_call *call, rxrpc_serial_t serial,
4162306a36Sopenharmony_ci			     enum rxrpc_propose_ack_trace why)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	unsigned long expiry = rxrpc_soft_ack_delay;
4462306a36Sopenharmony_ci	unsigned long now = jiffies, ack_at;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	if (rxrpc_soft_ack_delay < expiry)
4762306a36Sopenharmony_ci		expiry = rxrpc_soft_ack_delay;
4862306a36Sopenharmony_ci	if (call->peer->srtt_us != 0)
4962306a36Sopenharmony_ci		ack_at = usecs_to_jiffies(call->peer->srtt_us >> 3);
5062306a36Sopenharmony_ci	else
5162306a36Sopenharmony_ci		ack_at = expiry;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	ack_at += READ_ONCE(call->tx_backoff);
5462306a36Sopenharmony_ci	ack_at += now;
5562306a36Sopenharmony_ci	if (time_before(ack_at, call->delay_ack_at)) {
5662306a36Sopenharmony_ci		WRITE_ONCE(call->delay_ack_at, ack_at);
5762306a36Sopenharmony_ci		rxrpc_reduce_call_timer(call, ack_at, now,
5862306a36Sopenharmony_ci					rxrpc_timer_set_for_ack);
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	trace_rxrpc_propose_ack(call, why, RXRPC_ACK_DELAY, serial);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/*
6562306a36Sopenharmony_ci * Queue an ACK for immediate transmission.
6662306a36Sopenharmony_ci */
6762306a36Sopenharmony_civoid rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason,
6862306a36Sopenharmony_ci		    rxrpc_serial_t serial, enum rxrpc_propose_ack_trace why)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	struct rxrpc_txbuf *txb;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
7362306a36Sopenharmony_ci		return;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	rxrpc_inc_stat(call->rxnet, stat_tx_acks[ack_reason]);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	txb = rxrpc_alloc_txbuf(call, RXRPC_PACKET_TYPE_ACK,
7862306a36Sopenharmony_ci				rcu_read_lock_held() ? GFP_ATOMIC | __GFP_NOWARN : GFP_NOFS);
7962306a36Sopenharmony_ci	if (!txb) {
8062306a36Sopenharmony_ci		kleave(" = -ENOMEM");
8162306a36Sopenharmony_ci		return;
8262306a36Sopenharmony_ci	}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	txb->ack_why		= why;
8562306a36Sopenharmony_ci	txb->wire.seq		= 0;
8662306a36Sopenharmony_ci	txb->wire.type		= RXRPC_PACKET_TYPE_ACK;
8762306a36Sopenharmony_ci	txb->wire.flags		|= RXRPC_SLOW_START_OK;
8862306a36Sopenharmony_ci	txb->ack.bufferSpace	= 0;
8962306a36Sopenharmony_ci	txb->ack.maxSkew	= 0;
9062306a36Sopenharmony_ci	txb->ack.firstPacket	= 0;
9162306a36Sopenharmony_ci	txb->ack.previousPacket	= 0;
9262306a36Sopenharmony_ci	txb->ack.serial		= htonl(serial);
9362306a36Sopenharmony_ci	txb->ack.reason		= ack_reason;
9462306a36Sopenharmony_ci	txb->ack.nAcks		= 0;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	trace_rxrpc_send_ack(call, why, ack_reason, serial);
9762306a36Sopenharmony_ci	rxrpc_send_ack_packet(call, txb);
9862306a36Sopenharmony_ci	rxrpc_put_txbuf(txb, rxrpc_txbuf_put_ack_tx);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/*
10262306a36Sopenharmony_ci * Handle congestion being detected by the retransmit timeout.
10362306a36Sopenharmony_ci */
10462306a36Sopenharmony_cistatic void rxrpc_congestion_timeout(struct rxrpc_call *call)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	set_bit(RXRPC_CALL_RETRANS_TIMEOUT, &call->flags);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/*
11062306a36Sopenharmony_ci * Perform retransmission of NAK'd and unack'd packets.
11162306a36Sopenharmony_ci */
11262306a36Sopenharmony_civoid rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	struct rxrpc_ackpacket *ack = NULL;
11562306a36Sopenharmony_ci	struct rxrpc_skb_priv *sp;
11662306a36Sopenharmony_ci	struct rxrpc_txbuf *txb;
11762306a36Sopenharmony_ci	unsigned long resend_at;
11862306a36Sopenharmony_ci	rxrpc_seq_t transmitted = READ_ONCE(call->tx_transmitted);
11962306a36Sopenharmony_ci	ktime_t now, max_age, oldest, ack_ts;
12062306a36Sopenharmony_ci	bool unacked = false;
12162306a36Sopenharmony_ci	unsigned int i;
12262306a36Sopenharmony_ci	LIST_HEAD(retrans_queue);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	_enter("{%d,%d}", call->acks_hard_ack, call->tx_top);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	now = ktime_get_real();
12762306a36Sopenharmony_ci	max_age = ktime_sub_us(now, jiffies_to_usecs(call->peer->rto_j));
12862306a36Sopenharmony_ci	oldest = now;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	if (list_empty(&call->tx_buffer))
13162306a36Sopenharmony_ci		goto no_resend;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	if (list_empty(&call->tx_buffer))
13462306a36Sopenharmony_ci		goto no_further_resend;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	trace_rxrpc_resend(call, ack_skb);
13762306a36Sopenharmony_ci	txb = list_first_entry(&call->tx_buffer, struct rxrpc_txbuf, call_link);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	/* Scan the soft ACK table without dropping the lock and resend any
14062306a36Sopenharmony_ci	 * explicitly NAK'd packets.
14162306a36Sopenharmony_ci	 */
14262306a36Sopenharmony_ci	if (ack_skb) {
14362306a36Sopenharmony_ci		sp = rxrpc_skb(ack_skb);
14462306a36Sopenharmony_ci		ack = (void *)ack_skb->data + sizeof(struct rxrpc_wire_header);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci		for (i = 0; i < sp->nr_acks; i++) {
14762306a36Sopenharmony_ci			rxrpc_seq_t seq;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci			if (ack->acks[i] & 1)
15062306a36Sopenharmony_ci				continue;
15162306a36Sopenharmony_ci			seq = sp->first_ack + i;
15262306a36Sopenharmony_ci			if (after(txb->seq, transmitted))
15362306a36Sopenharmony_ci				break;
15462306a36Sopenharmony_ci			if (after(txb->seq, seq))
15562306a36Sopenharmony_ci				continue; /* A new hard ACK probably came in */
15662306a36Sopenharmony_ci			list_for_each_entry_from(txb, &call->tx_buffer, call_link) {
15762306a36Sopenharmony_ci				if (txb->seq == seq)
15862306a36Sopenharmony_ci					goto found_txb;
15962306a36Sopenharmony_ci			}
16062306a36Sopenharmony_ci			goto no_further_resend;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci		found_txb:
16362306a36Sopenharmony_ci			if (after(ntohl(txb->wire.serial), call->acks_highest_serial))
16462306a36Sopenharmony_ci				continue; /* Ack point not yet reached */
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci			rxrpc_see_txbuf(txb, rxrpc_txbuf_see_unacked);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci			if (list_empty(&txb->tx_link)) {
16962306a36Sopenharmony_ci				list_add_tail(&txb->tx_link, &retrans_queue);
17062306a36Sopenharmony_ci				set_bit(RXRPC_TXBUF_RESENT, &txb->flags);
17162306a36Sopenharmony_ci			}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci			trace_rxrpc_retransmit(call, txb->seq,
17462306a36Sopenharmony_ci					       ktime_to_ns(ktime_sub(txb->last_sent,
17562306a36Sopenharmony_ci								     max_age)));
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci			if (list_is_last(&txb->call_link, &call->tx_buffer))
17862306a36Sopenharmony_ci				goto no_further_resend;
17962306a36Sopenharmony_ci			txb = list_next_entry(txb, call_link);
18062306a36Sopenharmony_ci		}
18162306a36Sopenharmony_ci	}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	/* Fast-forward through the Tx queue to the point the peer says it has
18462306a36Sopenharmony_ci	 * seen.  Anything between the soft-ACK table and that point will get
18562306a36Sopenharmony_ci	 * ACK'd or NACK'd in due course, so don't worry about it here; here we
18662306a36Sopenharmony_ci	 * need to consider retransmitting anything beyond that point.
18762306a36Sopenharmony_ci	 *
18862306a36Sopenharmony_ci	 * Note that ACK for a packet can beat the update of tx_transmitted.
18962306a36Sopenharmony_ci	 */
19062306a36Sopenharmony_ci	if (after_eq(READ_ONCE(call->acks_prev_seq), READ_ONCE(call->tx_transmitted)))
19162306a36Sopenharmony_ci		goto no_further_resend;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	list_for_each_entry_from(txb, &call->tx_buffer, call_link) {
19462306a36Sopenharmony_ci		if (before_eq(txb->seq, READ_ONCE(call->acks_prev_seq)))
19562306a36Sopenharmony_ci			continue;
19662306a36Sopenharmony_ci		if (after(txb->seq, READ_ONCE(call->tx_transmitted)))
19762306a36Sopenharmony_ci			break; /* Not transmitted yet */
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci		if (ack && ack->reason == RXRPC_ACK_PING_RESPONSE &&
20062306a36Sopenharmony_ci		    before(ntohl(txb->wire.serial), ntohl(ack->serial)))
20162306a36Sopenharmony_ci			goto do_resend; /* Wasn't accounted for by a more recent ping. */
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci		if (ktime_after(txb->last_sent, max_age)) {
20462306a36Sopenharmony_ci			if (ktime_before(txb->last_sent, oldest))
20562306a36Sopenharmony_ci				oldest = txb->last_sent;
20662306a36Sopenharmony_ci			continue;
20762306a36Sopenharmony_ci		}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	do_resend:
21062306a36Sopenharmony_ci		unacked = true;
21162306a36Sopenharmony_ci		if (list_empty(&txb->tx_link)) {
21262306a36Sopenharmony_ci			list_add_tail(&txb->tx_link, &retrans_queue);
21362306a36Sopenharmony_ci			set_bit(RXRPC_TXBUF_RESENT, &txb->flags);
21462306a36Sopenharmony_ci			rxrpc_inc_stat(call->rxnet, stat_tx_data_retrans);
21562306a36Sopenharmony_ci		}
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cino_further_resend:
21962306a36Sopenharmony_cino_resend:
22062306a36Sopenharmony_ci	resend_at = nsecs_to_jiffies(ktime_to_ns(ktime_sub(now, oldest)));
22162306a36Sopenharmony_ci	resend_at += jiffies + rxrpc_get_rto_backoff(call->peer,
22262306a36Sopenharmony_ci						     !list_empty(&retrans_queue));
22362306a36Sopenharmony_ci	WRITE_ONCE(call->resend_at, resend_at);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	if (unacked)
22662306a36Sopenharmony_ci		rxrpc_congestion_timeout(call);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	/* If there was nothing that needed retransmission then it's likely
22962306a36Sopenharmony_ci	 * that an ACK got lost somewhere.  Send a ping to find out instead of
23062306a36Sopenharmony_ci	 * retransmitting data.
23162306a36Sopenharmony_ci	 */
23262306a36Sopenharmony_ci	if (list_empty(&retrans_queue)) {
23362306a36Sopenharmony_ci		rxrpc_reduce_call_timer(call, resend_at, jiffies,
23462306a36Sopenharmony_ci					rxrpc_timer_set_for_resend);
23562306a36Sopenharmony_ci		ack_ts = ktime_sub(now, call->acks_latest_ts);
23662306a36Sopenharmony_ci		if (ktime_to_us(ack_ts) < (call->peer->srtt_us >> 3))
23762306a36Sopenharmony_ci			goto out;
23862306a36Sopenharmony_ci		rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
23962306a36Sopenharmony_ci			       rxrpc_propose_ack_ping_for_lost_ack);
24062306a36Sopenharmony_ci		goto out;
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	/* Retransmit the queue */
24462306a36Sopenharmony_ci	while ((txb = list_first_entry_or_null(&retrans_queue,
24562306a36Sopenharmony_ci					       struct rxrpc_txbuf, tx_link))) {
24662306a36Sopenharmony_ci		list_del_init(&txb->tx_link);
24762306a36Sopenharmony_ci		rxrpc_transmit_one(call, txb);
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ciout:
25162306a36Sopenharmony_ci	_leave("");
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci/*
25562306a36Sopenharmony_ci * Start transmitting the reply to a service.  This cancels the need to ACK the
25662306a36Sopenharmony_ci * request if we haven't yet done so.
25762306a36Sopenharmony_ci */
25862306a36Sopenharmony_cistatic void rxrpc_begin_service_reply(struct rxrpc_call *call)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	unsigned long now = jiffies;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	rxrpc_set_call_state(call, RXRPC_CALL_SERVER_SEND_REPLY);
26362306a36Sopenharmony_ci	WRITE_ONCE(call->delay_ack_at, now + MAX_JIFFY_OFFSET);
26462306a36Sopenharmony_ci	if (call->ackr_reason == RXRPC_ACK_DELAY)
26562306a36Sopenharmony_ci		call->ackr_reason = 0;
26662306a36Sopenharmony_ci	trace_rxrpc_timer(call, rxrpc_timer_init_for_send_reply, now);
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci/*
27062306a36Sopenharmony_ci * Close the transmission phase.  After this point there is no more data to be
27162306a36Sopenharmony_ci * transmitted in the call.
27262306a36Sopenharmony_ci */
27362306a36Sopenharmony_cistatic void rxrpc_close_tx_phase(struct rxrpc_call *call)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	_debug("________awaiting reply/ACK__________");
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	switch (__rxrpc_call_state(call)) {
27862306a36Sopenharmony_ci	case RXRPC_CALL_CLIENT_SEND_REQUEST:
27962306a36Sopenharmony_ci		rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_AWAIT_REPLY);
28062306a36Sopenharmony_ci		break;
28162306a36Sopenharmony_ci	case RXRPC_CALL_SERVER_SEND_REPLY:
28262306a36Sopenharmony_ci		rxrpc_set_call_state(call, RXRPC_CALL_SERVER_AWAIT_ACK);
28362306a36Sopenharmony_ci		break;
28462306a36Sopenharmony_ci	default:
28562306a36Sopenharmony_ci		break;
28662306a36Sopenharmony_ci	}
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_cistatic bool rxrpc_tx_window_has_space(struct rxrpc_call *call)
29062306a36Sopenharmony_ci{
29162306a36Sopenharmony_ci	unsigned int winsize = min_t(unsigned int, call->tx_winsize,
29262306a36Sopenharmony_ci				     call->cong_cwnd + call->cong_extra);
29362306a36Sopenharmony_ci	rxrpc_seq_t window = call->acks_hard_ack, wtop = window + winsize;
29462306a36Sopenharmony_ci	rxrpc_seq_t tx_top = call->tx_top;
29562306a36Sopenharmony_ci	int space;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	space = wtop - tx_top;
29862306a36Sopenharmony_ci	return space > 0;
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci/*
30262306a36Sopenharmony_ci * Decant some if the sendmsg prepared queue into the transmission buffer.
30362306a36Sopenharmony_ci */
30462306a36Sopenharmony_cistatic void rxrpc_decant_prepared_tx(struct rxrpc_call *call)
30562306a36Sopenharmony_ci{
30662306a36Sopenharmony_ci	struct rxrpc_txbuf *txb;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	if (!test_bit(RXRPC_CALL_EXPOSED, &call->flags)) {
30962306a36Sopenharmony_ci		if (list_empty(&call->tx_sendmsg))
31062306a36Sopenharmony_ci			return;
31162306a36Sopenharmony_ci		rxrpc_expose_client_call(call);
31262306a36Sopenharmony_ci	}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	while ((txb = list_first_entry_or_null(&call->tx_sendmsg,
31562306a36Sopenharmony_ci					       struct rxrpc_txbuf, call_link))) {
31662306a36Sopenharmony_ci		spin_lock(&call->tx_lock);
31762306a36Sopenharmony_ci		list_del(&txb->call_link);
31862306a36Sopenharmony_ci		spin_unlock(&call->tx_lock);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci		call->tx_top = txb->seq;
32162306a36Sopenharmony_ci		list_add_tail(&txb->call_link, &call->tx_buffer);
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci		if (txb->wire.flags & RXRPC_LAST_PACKET)
32462306a36Sopenharmony_ci			rxrpc_close_tx_phase(call);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci		rxrpc_transmit_one(call, txb);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci		if (!rxrpc_tx_window_has_space(call))
32962306a36Sopenharmony_ci			break;
33062306a36Sopenharmony_ci	}
33162306a36Sopenharmony_ci}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cistatic void rxrpc_transmit_some_data(struct rxrpc_call *call)
33462306a36Sopenharmony_ci{
33562306a36Sopenharmony_ci	switch (__rxrpc_call_state(call)) {
33662306a36Sopenharmony_ci	case RXRPC_CALL_SERVER_ACK_REQUEST:
33762306a36Sopenharmony_ci		if (list_empty(&call->tx_sendmsg))
33862306a36Sopenharmony_ci			return;
33962306a36Sopenharmony_ci		rxrpc_begin_service_reply(call);
34062306a36Sopenharmony_ci		fallthrough;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	case RXRPC_CALL_SERVER_SEND_REPLY:
34362306a36Sopenharmony_ci	case RXRPC_CALL_CLIENT_SEND_REQUEST:
34462306a36Sopenharmony_ci		if (!rxrpc_tx_window_has_space(call))
34562306a36Sopenharmony_ci			return;
34662306a36Sopenharmony_ci		if (list_empty(&call->tx_sendmsg)) {
34762306a36Sopenharmony_ci			rxrpc_inc_stat(call->rxnet, stat_tx_data_underflow);
34862306a36Sopenharmony_ci			return;
34962306a36Sopenharmony_ci		}
35062306a36Sopenharmony_ci		rxrpc_decant_prepared_tx(call);
35162306a36Sopenharmony_ci		break;
35262306a36Sopenharmony_ci	default:
35362306a36Sopenharmony_ci		return;
35462306a36Sopenharmony_ci	}
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci/*
35862306a36Sopenharmony_ci * Ping the other end to fill our RTT cache and to retrieve the rwind
35962306a36Sopenharmony_ci * and MTU parameters.
36062306a36Sopenharmony_ci */
36162306a36Sopenharmony_cistatic void rxrpc_send_initial_ping(struct rxrpc_call *call)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	if (call->peer->rtt_count < 3 ||
36462306a36Sopenharmony_ci	    ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000),
36562306a36Sopenharmony_ci			 ktime_get_real()))
36662306a36Sopenharmony_ci		rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
36762306a36Sopenharmony_ci			       rxrpc_propose_ack_ping_for_params);
36862306a36Sopenharmony_ci}
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci/*
37162306a36Sopenharmony_ci * Handle retransmission and deferred ACK/abort generation.
37262306a36Sopenharmony_ci */
37362306a36Sopenharmony_cibool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	unsigned long now, next, t;
37662306a36Sopenharmony_ci	bool resend = false, expired = false;
37762306a36Sopenharmony_ci	s32 abort_code;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	rxrpc_see_call(call, rxrpc_call_see_input);
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	//printk("\n--------------------\n");
38262306a36Sopenharmony_ci	_enter("{%d,%s,%lx}",
38362306a36Sopenharmony_ci	       call->debug_id, rxrpc_call_states[__rxrpc_call_state(call)],
38462306a36Sopenharmony_ci	       call->events);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	if (__rxrpc_call_is_complete(call))
38762306a36Sopenharmony_ci		goto out;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	/* Handle abort request locklessly, vs rxrpc_propose_abort(). */
39062306a36Sopenharmony_ci	abort_code = smp_load_acquire(&call->send_abort);
39162306a36Sopenharmony_ci	if (abort_code) {
39262306a36Sopenharmony_ci		rxrpc_abort_call(call, 0, call->send_abort, call->send_abort_err,
39362306a36Sopenharmony_ci				 call->send_abort_why);
39462306a36Sopenharmony_ci		goto out;
39562306a36Sopenharmony_ci	}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	if (skb && skb->mark == RXRPC_SKB_MARK_ERROR)
39862306a36Sopenharmony_ci		goto out;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	/* If we see our async-event poke, check for timeout trippage. */
40162306a36Sopenharmony_ci	now = jiffies;
40262306a36Sopenharmony_ci	t = READ_ONCE(call->expect_rx_by);
40362306a36Sopenharmony_ci	if (time_after_eq(now, t)) {
40462306a36Sopenharmony_ci		trace_rxrpc_timer(call, rxrpc_timer_exp_normal, now);
40562306a36Sopenharmony_ci		expired = true;
40662306a36Sopenharmony_ci	}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	t = READ_ONCE(call->expect_req_by);
40962306a36Sopenharmony_ci	if (__rxrpc_call_state(call) == RXRPC_CALL_SERVER_RECV_REQUEST &&
41062306a36Sopenharmony_ci	    time_after_eq(now, t)) {
41162306a36Sopenharmony_ci		trace_rxrpc_timer(call, rxrpc_timer_exp_idle, now);
41262306a36Sopenharmony_ci		expired = true;
41362306a36Sopenharmony_ci	}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	t = READ_ONCE(call->expect_term_by);
41662306a36Sopenharmony_ci	if (time_after_eq(now, t)) {
41762306a36Sopenharmony_ci		trace_rxrpc_timer(call, rxrpc_timer_exp_hard, now);
41862306a36Sopenharmony_ci		expired = true;
41962306a36Sopenharmony_ci	}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	t = READ_ONCE(call->delay_ack_at);
42262306a36Sopenharmony_ci	if (time_after_eq(now, t)) {
42362306a36Sopenharmony_ci		trace_rxrpc_timer(call, rxrpc_timer_exp_ack, now);
42462306a36Sopenharmony_ci		cmpxchg(&call->delay_ack_at, t, now + MAX_JIFFY_OFFSET);
42562306a36Sopenharmony_ci		rxrpc_send_ACK(call, RXRPC_ACK_DELAY, 0,
42662306a36Sopenharmony_ci			       rxrpc_propose_ack_ping_for_lost_ack);
42762306a36Sopenharmony_ci	}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	t = READ_ONCE(call->ack_lost_at);
43062306a36Sopenharmony_ci	if (time_after_eq(now, t)) {
43162306a36Sopenharmony_ci		trace_rxrpc_timer(call, rxrpc_timer_exp_lost_ack, now);
43262306a36Sopenharmony_ci		cmpxchg(&call->ack_lost_at, t, now + MAX_JIFFY_OFFSET);
43362306a36Sopenharmony_ci		set_bit(RXRPC_CALL_EV_ACK_LOST, &call->events);
43462306a36Sopenharmony_ci	}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	t = READ_ONCE(call->keepalive_at);
43762306a36Sopenharmony_ci	if (time_after_eq(now, t)) {
43862306a36Sopenharmony_ci		trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now);
43962306a36Sopenharmony_ci		cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET);
44062306a36Sopenharmony_ci		rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
44162306a36Sopenharmony_ci			       rxrpc_propose_ack_ping_for_keepalive);
44262306a36Sopenharmony_ci	}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	t = READ_ONCE(call->ping_at);
44562306a36Sopenharmony_ci	if (time_after_eq(now, t)) {
44662306a36Sopenharmony_ci		trace_rxrpc_timer(call, rxrpc_timer_exp_ping, now);
44762306a36Sopenharmony_ci		cmpxchg(&call->ping_at, t, now + MAX_JIFFY_OFFSET);
44862306a36Sopenharmony_ci		rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
44962306a36Sopenharmony_ci			       rxrpc_propose_ack_ping_for_keepalive);
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	t = READ_ONCE(call->resend_at);
45362306a36Sopenharmony_ci	if (time_after_eq(now, t)) {
45462306a36Sopenharmony_ci		trace_rxrpc_timer(call, rxrpc_timer_exp_resend, now);
45562306a36Sopenharmony_ci		cmpxchg(&call->resend_at, t, now + MAX_JIFFY_OFFSET);
45662306a36Sopenharmony_ci		resend = true;
45762306a36Sopenharmony_ci	}
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	if (skb)
46062306a36Sopenharmony_ci		rxrpc_input_call_packet(call, skb);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	rxrpc_transmit_some_data(call);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	if (skb) {
46562306a36Sopenharmony_ci		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci		if (sp->hdr.type == RXRPC_PACKET_TYPE_ACK)
46862306a36Sopenharmony_ci			rxrpc_congestion_degrade(call);
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	if (test_and_clear_bit(RXRPC_CALL_EV_INITIAL_PING, &call->events))
47262306a36Sopenharmony_ci		rxrpc_send_initial_ping(call);
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	/* Process events */
47562306a36Sopenharmony_ci	if (expired) {
47662306a36Sopenharmony_ci		if (test_bit(RXRPC_CALL_RX_HEARD, &call->flags) &&
47762306a36Sopenharmony_ci		    (int)call->conn->hi_serial - (int)call->rx_serial > 0) {
47862306a36Sopenharmony_ci			trace_rxrpc_call_reset(call);
47962306a36Sopenharmony_ci			rxrpc_abort_call(call, 0, RX_CALL_DEAD, -ECONNRESET,
48062306a36Sopenharmony_ci					 rxrpc_abort_call_reset);
48162306a36Sopenharmony_ci		} else {
48262306a36Sopenharmony_ci			rxrpc_abort_call(call, 0, RX_CALL_TIMEOUT, -ETIME,
48362306a36Sopenharmony_ci					 rxrpc_abort_call_timeout);
48462306a36Sopenharmony_ci		}
48562306a36Sopenharmony_ci		goto out;
48662306a36Sopenharmony_ci	}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events))
48962306a36Sopenharmony_ci		rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
49062306a36Sopenharmony_ci			       rxrpc_propose_ack_ping_for_lost_ack);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	if (resend && __rxrpc_call_state(call) != RXRPC_CALL_CLIENT_RECV_REPLY)
49362306a36Sopenharmony_ci		rxrpc_resend(call, NULL);
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	if (test_and_clear_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags))
49662306a36Sopenharmony_ci		rxrpc_send_ACK(call, RXRPC_ACK_IDLE, 0,
49762306a36Sopenharmony_ci			       rxrpc_propose_ack_rx_idle);
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	if (call->ackr_nr_unacked > 2) {
50062306a36Sopenharmony_ci		if (call->peer->rtt_count < 3)
50162306a36Sopenharmony_ci			rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
50262306a36Sopenharmony_ci				       rxrpc_propose_ack_ping_for_rtt);
50362306a36Sopenharmony_ci		else if (ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000),
50462306a36Sopenharmony_ci				      ktime_get_real()))
50562306a36Sopenharmony_ci			rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
50662306a36Sopenharmony_ci				       rxrpc_propose_ack_ping_for_old_rtt);
50762306a36Sopenharmony_ci		else
50862306a36Sopenharmony_ci			rxrpc_send_ACK(call, RXRPC_ACK_IDLE, 0,
50962306a36Sopenharmony_ci				       rxrpc_propose_ack_input_data);
51062306a36Sopenharmony_ci	}
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	/* Make sure the timer is restarted */
51362306a36Sopenharmony_ci	if (!__rxrpc_call_is_complete(call)) {
51462306a36Sopenharmony_ci		next = call->expect_rx_by;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci#define set(T) { t = READ_ONCE(T); if (time_before(t, next)) next = t; }
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci		set(call->expect_req_by);
51962306a36Sopenharmony_ci		set(call->expect_term_by);
52062306a36Sopenharmony_ci		set(call->delay_ack_at);
52162306a36Sopenharmony_ci		set(call->ack_lost_at);
52262306a36Sopenharmony_ci		set(call->resend_at);
52362306a36Sopenharmony_ci		set(call->keepalive_at);
52462306a36Sopenharmony_ci		set(call->ping_at);
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci		now = jiffies;
52762306a36Sopenharmony_ci		if (time_after_eq(now, next))
52862306a36Sopenharmony_ci			rxrpc_poke_call(call, rxrpc_call_poke_timer_now);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci		rxrpc_reduce_call_timer(call, next, now, rxrpc_timer_restart);
53162306a36Sopenharmony_ci	}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ciout:
53462306a36Sopenharmony_ci	if (__rxrpc_call_is_complete(call)) {
53562306a36Sopenharmony_ci		del_timer_sync(&call->timer);
53662306a36Sopenharmony_ci		if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
53762306a36Sopenharmony_ci			rxrpc_disconnect_call(call);
53862306a36Sopenharmony_ci		if (call->security)
53962306a36Sopenharmony_ci			call->security->free_call_crypto(call);
54062306a36Sopenharmony_ci	}
54162306a36Sopenharmony_ci	if (call->acks_hard_ack != call->tx_bottom)
54262306a36Sopenharmony_ci		rxrpc_shrink_call_tx_buffer(call);
54362306a36Sopenharmony_ci	_leave("");
54462306a36Sopenharmony_ci	return true;
54562306a36Sopenharmony_ci}
546