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