aboutsummaryrefslogtreecommitdiff
path: root/net/rxrpc/input.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-04-12 16:57:23 -0700
committerDavid S. Miller <davem@davemloft.net>2019-04-12 16:57:23 -0700
commit9e550f015303a99a9395a838743bbeff94d4d49c (patch)
treeadec0da77205b01e590914e28aca0930926f9949 /net/rxrpc/input.c
parent1dc2b3d65523780ed1972d446c76e62e13f3e8f5 (diff)
parent1a2391c30c0b9d041bc340f68df81d49c53546cc (diff)
Merge branch 'rxrpc-fixes'
David Howells says: ==================== rxrpc: Fixes Here is a collection of fixes for rxrpc: (1) rxrpc_error_report() needs to call sock_error() to clear the error code from the UDP transport socket, lest it be unexpectedly revisited on the next kernel_sendmsg() call. This has been causing all sorts of weird effects in AFS as the effects have typically been felt by the wrong RxRPC call. (2) Allow a kernel user of AF_RXRPC to easily detect if an rxrpc call has completed. (3) Allow errors incurred by attempting to transmit data through the UDP socket to get back up the stack to AFS. (4) Make AFS use (2) to abort the synchronous-mode call waiting loop if the rxrpc-level call completed. (5) Add a missing tracepoint case for tracing abort reception. (6) Fix detection and handling of out-of-order ACKs. ==================== Tested-by: Jonathan Billings <jsbillin@umich.edu> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/rxrpc/input.c')
-rw-r--r--net/rxrpc/input.c18
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);