From d5d9e67a9f6c9d3cc13ebca1829f6c348f26cfd5 Mon Sep 17 00:00:00 2001 From: Simon Wilkinson Date: Fri, 17 Jun 2011 19:38:29 +0100 Subject: [PATCH] rx: Account for delayed ACKS when computing RTO RX currently only soft ACKs every second packet, therefore a soft ACK may be delayed by a period of time (currently 100ms, although RX did expose this as a public variable in earlier versions). RTT values are computed using only non-delayed ACKs, so the timeout is a smoothed average of the exact time taken to send and directly ACK a packet. Therefore, if the peer ends up using a delayed ACK for the packet, using just the RTT will cause that packet to be timed out. A while ago, this was dealt with by padding the calculated RTT with an additional 350ms. This was then removed, and changed to a 350ms minimum value. When this caused large numbers of spurious resends, the padding was restored, but with a 20ms default value. As noted above, 20ms is too low, as we may wait for up to 100ms before sending an ACK. This patch changes minPeerTimeout so that it does what it says on the tin - sets a minimum value below which the peer timout may not fall. It then adds to either this value, or the calculated one, 200ms of padding. This makes our padding identical to TCPs, and allows some future leway as to the softAckDelay value. Reviewed-on: http://gerrit.openafs.org/4859 Reviewed-by: Derrick Brashear Tested-by: BuildBot (cherry picked from commit 699330682f3cb001bf1bfbeaffd806600ccf69e8) Change-Id: Ibe06f46c9ac846fb0381c467242e5c3b439c8907 Reviewed-on: http://gerrit.openafs.org/4910 Tested-by: BuildBot Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- src/rx/rx.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/rx/rx.c b/src/rx/rx.c index d04670b6f..1f85946f7 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -6777,11 +6777,16 @@ rxi_ComputeRoundTripTime(struct rx_packet *p, peer->rtt = _8THMSEC(&thisRtt) + 8; peer->rtt_dev = peer->rtt >> 2; /* rtt/2: they're scaled differently */ } - /* the timeout is RTT + 4*MDEV + rx_minPeerTimeout msec. - * This is because one end or the other of these connections is usually - * in a user process, and can be switched and/or swapped out. So on fast, - * reliable networks, the timeout would otherwise be too short. */ - rtt_timeout = ((peer->rtt >> 3) + peer->rtt_dev) + rx_minPeerTimeout; + /* the smoothed RTT time is RTT + 4*MDEV + * + * We allow a user specified minimum to be set for this, to allow clamping + * at a minimum value in the same way as TCP. In addition, we have to allow + * for the possibility that this packet is answered by a delayed ACK, so we + * add on a fixed 200ms to account for that timer expiring. + */ + + rtt_timeout = MAX(((peer->rtt >> 3) + peer->rtt_dev), + rx_minPeerTimeout) + 200; clock_Zero(&(peer->timeout)); clock_Addmsec(&(peer->timeout), rtt_timeout); -- 2.39.5