Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2fd958ae authored by David Howells's avatar David Howells Committed by Greg Kroah-Hartman
Browse files

rxrpc: Fix overlapping ACK accounting



[ Upstream commit 8940ba3cfe4841928777fd45eaa92051522c7f0c ]

Fix accidental overlapping of Rx-phase ACK accounting with Tx-phase ACK
accounting through variables shared between the two.  call->acks_* members
refer to ACKs received in the Tx phase and call->ackr_* members to ACKs
sent/to be sent during the Rx phase.

Fixes: 1a2391c3 ("rxrpc: Fix detection of out of order acks")
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 5aa14daf
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -665,10 +665,9 @@ struct rxrpc_call {

	spinlock_t		input_lock;	/* Lock for packet input to this call */

	/* receive-phase ACK management */
	/* Receive-phase ACK management (ACKs we send). */
	u8			ackr_reason;	/* reason to ACK */
	rxrpc_serial_t		ackr_serial;	/* serial of packet being ACK'd */
	rxrpc_serial_t		ackr_first_seq;	/* first sequence number received */
	rxrpc_seq_t		ackr_prev_seq;	/* previous sequence number received */
	rxrpc_seq_t		ackr_consumed;	/* Highest packet shown consumed */
	rxrpc_seq_t		ackr_seen;	/* Highest packet shown seen */
@@ -677,8 +676,10 @@ struct rxrpc_call {
	rxrpc_serial_t		ping_serial;	/* Last ping sent */
	ktime_t			ping_time;	/* Time last ping sent */

	/* transmission-phase ACK management */
	/* Transmission-phase ACK management (ACKs we've received). */
	ktime_t			acks_latest_ts;	/* Timestamp of latest ACK received */
	rxrpc_seq_t		acks_first_seq;	/* first sequence number received */
	rxrpc_seq_t		acks_prev_seq;	/* previous sequence number received */
	rxrpc_seq_t		acks_lowest_nak; /* Lowest NACK in the buffer (or ==tx_hard_ack) */
	rxrpc_seq_t		acks_lost_top;	/* tx_top at the time lost-ack ping sent */
	rxrpc_serial_t		acks_lost_ping;	/* Serial number of probe ACK */
+8 −8
Original line number Diff line number Diff line
@@ -808,7 +808,7 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
static bool rxrpc_is_ack_valid(struct rxrpc_call *call,
			       rxrpc_seq_t first_pkt, rxrpc_seq_t prev_pkt)
{
	rxrpc_seq_t base = READ_ONCE(call->ackr_first_seq);
	rxrpc_seq_t base = READ_ONCE(call->acks_first_seq);

	if (after(first_pkt, base))
		return true; /* The window advanced */
@@ -816,7 +816,7 @@ static bool rxrpc_is_ack_valid(struct rxrpc_call *call,
	if (before(first_pkt, base))
		return false; /* firstPacket regressed */

	if (after_eq(prev_pkt, call->ackr_prev_seq))
	if (after_eq(prev_pkt, call->acks_prev_seq))
		return true; /* previousPacket hasn't regressed. */

	/* Some rx implementations put a serial number in previousPacket. */
@@ -891,8 +891,8 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
	/* Discard any out-of-order or duplicate ACKs (outside lock). */
	if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
		trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
					   first_soft_ack, call->ackr_first_seq,
					   prev_pkt, call->ackr_prev_seq);
					   first_soft_ack, call->acks_first_seq,
					   prev_pkt, call->acks_prev_seq);
		return;
	}

@@ -907,14 +907,14 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
	/* Discard any out-of-order or duplicate ACKs (inside lock). */
	if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
		trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
					   first_soft_ack, call->ackr_first_seq,
					   prev_pkt, call->ackr_prev_seq);
					   first_soft_ack, call->acks_first_seq,
					   prev_pkt, call->acks_prev_seq);
		goto out;
	}
	call->acks_latest_ts = skb->tstamp;

	call->ackr_first_seq = first_soft_ack;
	call->ackr_prev_seq = prev_pkt;
	call->acks_first_seq = first_soft_ack;
	call->acks_prev_seq = prev_pkt;

	/* Parse rwind and mtu sizes if provided. */
	if (buf.info.rxMTU)