diff options
Diffstat (limited to 'net/rxrpc/input.c')
| -rw-r--r-- | net/rxrpc/input.c | 18 | 
1 files changed, 12 insertions, 6 deletions
| diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index 9128aa0e40aa..4c6f9d0a00e7 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c @@ -837,7 +837,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,  		u8 acks[RXRPC_MAXACKS];  	} buf;  	rxrpc_serial_t acked_serial; -	rxrpc_seq_t first_soft_ack, hard_ack; +	rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt;  	int nr_acks, offset, ioffset;  	_enter(""); @@ -851,13 +851,14 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,  	acked_serial = ntohl(buf.ack.serial);  	first_soft_ack = ntohl(buf.ack.firstPacket); +	prev_pkt = ntohl(buf.ack.previousPacket);  	hard_ack = first_soft_ack - 1;  	nr_acks = buf.ack.nAcks;  	summary.ack_reason = (buf.ack.reason < RXRPC_ACK__INVALID ?  			      buf.ack.reason : RXRPC_ACK__INVALID);  	trace_rxrpc_rx_ack(call, sp->hdr.serial, acked_serial, -			   first_soft_ack, ntohl(buf.ack.previousPacket), +			   first_soft_ack, prev_pkt,  			   summary.ack_reason, nr_acks);  	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,  				  rxrpc_propose_ack_respond_to_ack);  	} -	/* Discard any out-of-order or duplicate ACKs. */ -	if (before_eq(sp->hdr.serial, call->acks_latest)) +	/* Discard any out-of-order or duplicate ACKs (outside lock). */ +	if (before(first_soft_ack, call->ackr_first_seq) || +	    before(prev_pkt, call->ackr_prev_seq))  		return;  	buf.info.rxMTU = 0; @@ -890,12 +892,16 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,  	spin_lock(&call->input_lock); -	/* Discard any out-of-order or duplicate ACKs. */ -	if (before_eq(sp->hdr.serial, call->acks_latest)) +	/* Discard any out-of-order or duplicate ACKs (inside lock). */ +	if (before(first_soft_ack, call->ackr_first_seq) || +	    before(prev_pkt, call->ackr_prev_seq))  		goto out;  	call->acks_latest_ts = skb->tstamp;  	call->acks_latest = sp->hdr.serial; +	call->ackr_first_seq = first_soft_ack; +	call->ackr_prev_seq = prev_pkt; +  	/* Parse rwind and mtu sizes if provided. */  	if (buf.info.rxMTU)  		rxrpc_input_ackinfo(call, skb, &buf.info); | 
