From 6cd845bdb528938c2b6a559c2f0d577436676f94 Mon Sep 17 00:00:00 2001 From: Nickolai Zeldovich Date: Tue, 27 Mar 2001 01:51:35 +0000 Subject: [PATCH] fix-rx-rtt-computation-when-delay-is-involved-20010326 " rx: attempt to fix incorrect rtt computation, possibly winning on performance for links with some packet loss. Currently, the rtt is computed as the time from the transmission of a packet until the receipt of the corresponding ack packet. But this includes a potential delay (rx_{soft,hard,last}AckDelay) on the client which results in an abnormally high rtt, and even more erroneous rtt_dev and retransmit timeout values. The proposed solution is to ignore RX_ACK_DELAY type ack packets for the purposes of rtt computations, and introduce another ack packet type for RX_ACK_DELAY-type acks which are sent immediately by the client. This should of course be backwards-compatible with existing clients. " --- src/rx/rx.c | 22 +++++++++++++++------- src/rx/rx.h | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/rx/rx.c b/src/rx/rx.c index 14b47afdc..7af02f374 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -3151,7 +3151,7 @@ nextloop:; } else if (call->nSoftAcks > (u_short)rxi_SoftAckRate) { rxevent_Cancel(call->delayedAckEvent, call, RX_CALL_REFCOUNT_DELAY); np = rxi_SendAck(call, np, seq, serial, flags, - RX_ACK_DELAY, istack); + RX_ACK_IDLE, istack); } else if (call->nSoftAcks) { clock_GetTime(&when); if (haveLast && !(flags & RX_CLIENT_INITIATED)) { @@ -3267,13 +3267,17 @@ struct rx_packet *rxi_ReceiveAckPacket(call, np, istack) if (tp->header.seq >= first) break; call->tfirst = tp->header.seq + 1; if (tp->header.serial == serial) { - rxi_ComputeRoundTripTime(tp, &tp->timeSent, peer); + /* Use RTT if not delayed by client. */ + if (ap->reason != RX_ACK_DELAY) + rxi_ComputeRoundTripTime(tp, &tp->timeSent, peer); #ifdef ADAPT_WINDOW rxi_ComputeRate(peer, call, tp, np, ap->reason); #endif } - else if ((tp->firstSerial == serial)) { - rxi_ComputeRoundTripTime(tp, &tp->firstSent, peer); + else if (tp->firstSerial == serial) { + /* Use RTT if not delayed by client. */ + if (ap->reason != RX_ACK_DELAY) + rxi_ComputeRoundTripTime(tp, &tp->firstSent, peer); #ifdef ADAPT_WINDOW rxi_ComputeRate(peer, call, tp, np, ap->reason); #endif @@ -3334,13 +3338,17 @@ struct rx_packet *rxi_ReceiveAckPacket(call, np, istack) #endif /* RX_ENABLE_LOCKS */ #endif /* AFS_GLOBAL_RXLOCK_KERNEL */ if (tp->header.serial == serial) { - rxi_ComputeRoundTripTime(tp, &tp->timeSent, peer); + /* Use RTT if not delayed by client. */ + if (ap->reason != RX_ACK_DELAY) + rxi_ComputeRoundTripTime(tp, &tp->timeSent, peer); #ifdef ADAPT_WINDOW rxi_ComputeRate(peer, call, tp, np, ap->reason); #endif } else if ((tp->firstSerial == serial)) { - rxi_ComputeRoundTripTime(tp, &tp->firstSent, peer); + /* Use RTT if not delayed by client. */ + if (ap->reason != RX_ACK_DELAY) + rxi_ComputeRoundTripTime(tp, &tp->firstSent, peer); #ifdef ADAPT_WINDOW rxi_ComputeRate(peer, call, tp, np, ap->reason); #endif @@ -3820,7 +3828,7 @@ register struct rx_call **newcallp; if (call->flags & RX_CALL_CLEARED) { /* send an ack now to start the packet flow up again */ call->flags &= ~RX_CALL_CLEARED; - rxi_SendAck(call, 0, 0, 0, 0, RX_ACK_DELAY, 0); + rxi_SendAck(call, 0, 0, 0, 0, RX_ACK_IDLE, 0); } #ifdef RX_ENABLE_LOCKS CV_SIGNAL(&sq->cv); diff --git a/src/rx/rx.h b/src/rx/rx.h index 9f7d24b53..7820cb068 100644 --- a/src/rx/rx.h +++ b/src/rx/rx.h @@ -690,6 +690,8 @@ struct rx_ackPacket { #define RX_ACK_PING 6 /* This is a keep-alive ack */ #define RX_ACK_PING_RESPONSE 7 /* Ack'ing because we were pinged */ #define RX_ACK_DELAY 8 /* Ack generated since nothing has happened since receiving packet */ +#define RX_ACK_IDLE 9 /* Similar to RX_ACK_DELAY, but can + be */ /* Packet acknowledgement type */ #define RX_ACK_TYPE_NACK 0 /* I Don't have this packet */ -- 2.39.5