rx: Add Karn-style backoffs to RX retransmits
authorSimon Wilkinson <sxw@your-file-system.com>
Sat, 18 Jun 2011 10:58:57 +0000 (11:58 +0100)
committerDerrick Brashear <shadow@dementia.org>
Wed, 22 Jun 2011 01:58:57 +0000 (18:58 -0700)
When we retransmit a packet, we may be doing so because the RTT of the
connection has grown dramatically larger than earlier within the call.
However, RX doesn't permit all ACKs to retransmitted packets to be
counted within the RTT calculation.

So, adopt the same approach as Karn developed for TCP, and as described
in detail in RFC2988. When a retransmit event occurs, backoff the
connection RTT by doubling its value, and hold at this doubled value
until either another retransmit occurs (in which case we back off again,
up to a predetermined ceiling), or we receive an ACK packet which we
can use within the RTT calculation, in which case we drop back down to
the newly measured value.

This change replaces the per-packet backoff strategy originally
implemented in RX (which, whilst allowing resent packets more chance of
arriving, doesn't help with computing a correct RTT).

Change-Id: I715dc673a0b379733e3be26fa594ea13f492a58f
Reviewed-on: http://gerrit.openafs.org/4865
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/rx/rx.c

index 772e5c2..ade91cd 100644 (file)
@@ -5919,6 +5919,7 @@ rxi_Resend(struct rxevent *event, void *arg0, void *arg1, int istack)
 {
     struct rx_call *call = arg0;
     struct rx_packet *p, *nxp;
+    struct clock maxTimeout = { 60, 0 };
 
     MUTEX_ENTER(&call->lock);
     /* Make sure that the event pointer is removed from the call
@@ -5947,6 +5948,16 @@ rxi_Resend(struct rxevent *event, void *arg0, void *arg1, int istack)
        if (!(p->flags & RX_PKTFLAG_ACKED))
            p->flags &= ~RX_PKTFLAG_SENT;
     }
+
+    /* We're resending, so we double the timeout of the call. This will be
+     * dropped back down by the first successful ACK that we receive.
+     *
+     * We apply a maximum value here of 60 second
+     */
+    clock_Add(&call->rto, &call->rto);
+    if (clock_Gt(&call->rto, &maxTimeout))
+       call->rto = maxTimeout;
+
     rxi_Start(call, istack);
 
 out: