From 587cc8652bab48da7282f49bedf2eff8ea1cc88e Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sun, 5 Jun 2011 16:02:46 -0400 Subject: [PATCH] rx: do not rxi_AckAll for one data packet call rxi_ReceiveDataPacket() calls rxi_AckAll() when the call reaches the RX_CALL_RECEIVE_DONE state to permit the caller to empty the transmit queue. That reduces the memory consumption of the caller and avoids unnecessary retransmits which the call is in process. If the call data consists of a single packet it is possible that Ping ACK packets sent as part of connection establishment could race with the ACKALL and be delivered out of order. If the Ping ACK is delivered second, it will be ignored by the peer forcing a two second delay in connection establishment. To avoid the race do not send an ACKALL for a single packet call. Reviewed-on: http://gerrit.openafs.org/4799 Reviewed-by: Jeffrey Altman Reviewed-by: Derrick Brashear Tested-by: BuildBot (cherry picked from commit ff30293624a7e31d585b9e8f2e1a439cf87b6524) Change-Id: Ic64917c40aa29f9e99c434ab2f9ba2e4abc38883 Reviewed-on: http://gerrit.openafs.org/4913 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- src/rx/rx.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/rx/rx.c b/src/rx/rx.c index 3b62030c8..b482ad200 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -3990,12 +3990,18 @@ rxi_ReceiveDataPacket(struct rx_call *call, * received. Always send a soft ack for the last packet in * the server's reply. * - * If we have received all of the packets for the call - * immediately send an RX_PACKET_TYPE_ACKALL packet so that - * the peer can empty its packet queue and cancel all resend - * events. + * If there was more than one packet received for the call + * and we have received all of them, immediately send an + * RX_PACKET_TYPE_ACKALL packet so that the peer can empty + * its packet transmit queue and cancel all resend events. + * + * When there is only one packet in the call there is a + * chance that we can race with Ping ACKs sent as part of + * connection establishment if the udp packets are delivered + * out of order. When the race occurs, a two second delay + * will occur while waiting for a new Ping ACK to be sent. */ - if (call->flags & RX_CALL_RECEIVE_DONE) { + if (!isFirst && (call->flags & RX_CALL_RECEIVE_DONE)) { rxevent_Cancel(call->delayedAckEvent, call, RX_CALL_REFCOUNT_DELAY); rxi_AckAll(NULL, call, 0); } else if (ackNeeded) { -- 2.39.5