rxrpc: Fix overlapping ACK accounting
authorDavid Howells <dhowells@redhat.com>
Sat, 21 May 2022 08:03:18 +0000 (09:03 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jun 2022 08:23:02 +0000 (10:23 +0200)
[ 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: 1a2391c30c0b ("rxrpc: Fix detection of out of order acks")
Signed-off-by: David 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: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/rxrpc/ar-internal.h
net/rxrpc/input.c

index 969e532..9a9688c 100644 (file)
@@ -676,10 +676,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 */
@@ -692,8 +691,10 @@ struct rxrpc_call {
 #define RXRPC_CALL_RTT_AVAIL_MASK      0xf
 #define RXRPC_CALL_RTT_PEND_SHIFT      8
 
-       /* 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 */
index 67d3eba..3da33b5 100644 (file)
@@ -812,7 +812,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 */
@@ -820,7 +820,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. */
@@ -933,8 +933,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;
        }
 
@@ -949,14 +949,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)