Skip to content

Commit 1a2391c

Browse files
jaltmandavem330
authored andcommitted
rxrpc: Fix detection of out of order acks
The rxrpc packet serial number cannot be safely used to compute out of order ack packets for several reasons: 1. The allocation of serial numbers cannot be assumed to imply the order by which acks are populated and transmitted. In some rxrpc implementations, delayed acks and ping acks are transmitted asynchronously to the receipt of data packets and so may be transmitted out of order. As a result, they can race with idle acks. 2. Serial numbers are allocated by the rxrpc connection and not the call and as such may wrap independently if multiple channels are in use. In any case, what matters is whether the ack packet provides new information relating to the bounds of the window (the firstPacket and previousPacket in the ACK data). Fix this by discarding packets that appear to wind back the window bounds rather than on serial number procession. Fixes: 298bc15 ("rxrpc: Only take the rwind and mtu values from latest ACK") Signed-off-by: Jeffrey Altman <[email protected]> Signed-off-by: David Howells <[email protected]> Tested-by: Marc Dionne <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 39ce675 commit 1a2391c

File tree

2 files changed

+13
-6
lines changed

2 files changed

+13
-6
lines changed

net/rxrpc/ar-internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,7 @@ struct rxrpc_call {
654654
u8 ackr_reason; /* reason to ACK */
655655
u16 ackr_skew; /* skew on packet being ACK'd */
656656
rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */
657+
rxrpc_serial_t ackr_first_seq; /* first sequence number received */
657658
rxrpc_seq_t ackr_prev_seq; /* previous sequence number received */
658659
rxrpc_seq_t ackr_consumed; /* Highest packet shown consumed */
659660
rxrpc_seq_t ackr_seen; /* Highest packet shown seen */

net/rxrpc/input.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
837837
u8 acks[RXRPC_MAXACKS];
838838
} buf;
839839
rxrpc_serial_t acked_serial;
840-
rxrpc_seq_t first_soft_ack, hard_ack;
840+
rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt;
841841
int nr_acks, offset, ioffset;
842842

843843
_enter("");
@@ -851,13 +851,14 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
851851

852852
acked_serial = ntohl(buf.ack.serial);
853853
first_soft_ack = ntohl(buf.ack.firstPacket);
854+
prev_pkt = ntohl(buf.ack.previousPacket);
854855
hard_ack = first_soft_ack - 1;
855856
nr_acks = buf.ack.nAcks;
856857
summary.ack_reason = (buf.ack.reason < RXRPC_ACK__INVALID ?
857858
buf.ack.reason : RXRPC_ACK__INVALID);
858859

859860
trace_rxrpc_rx_ack(call, sp->hdr.serial, acked_serial,
860-
first_soft_ack, ntohl(buf.ack.previousPacket),
861+
first_soft_ack, prev_pkt,
861862
summary.ack_reason, nr_acks);
862863

863864
if (buf.ack.reason == RXRPC_ACK_PING_RESPONSE)
@@ -878,8 +879,9 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
878879
rxrpc_propose_ack_respond_to_ack);
879880
}
880881

881-
/* Discard any out-of-order or duplicate ACKs. */
882-
if (before_eq(sp->hdr.serial, call->acks_latest))
882+
/* Discard any out-of-order or duplicate ACKs (outside lock). */
883+
if (before(first_soft_ack, call->ackr_first_seq) ||
884+
before(prev_pkt, call->ackr_prev_seq))
883885
return;
884886

885887
buf.info.rxMTU = 0;
@@ -890,12 +892,16 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
890892

891893
spin_lock(&call->input_lock);
892894

893-
/* Discard any out-of-order or duplicate ACKs. */
894-
if (before_eq(sp->hdr.serial, call->acks_latest))
895+
/* Discard any out-of-order or duplicate ACKs (inside lock). */
896+
if (before(first_soft_ack, call->ackr_first_seq) ||
897+
before(prev_pkt, call->ackr_prev_seq))
895898
goto out;
896899
call->acks_latest_ts = skb->tstamp;
897900
call->acks_latest = sp->hdr.serial;
898901

902+
call->ackr_first_seq = first_soft_ack;
903+
call->ackr_prev_seq = prev_pkt;
904+
899905
/* Parse rwind and mtu sizes if provided. */
900906
if (buf.info.rxMTU)
901907
rxrpc_input_ackinfo(call, skb, &buf.info);

0 commit comments

Comments
 (0)