$NetBSD: patch-db,v 1.1 1999/04/28 23:57:04 rvb Exp $

diff -u /usr/pkgsrc/net/coda-5.2.2/coda-src/rpc2/host.c ./coda-src/rpc2/host.c
--- /usr/pkgsrc/net/coda-5.2.2/coda-src/rpc2/host.c	Mon Apr 19 20:02:40 1999
+++ ./coda-src/rpc2/host.c	Mon Apr 26 14:05:08 1999
@@ -148,9 +148,8 @@
 
 	he->RTT       = 0;
 	he->RTTVar    = 0;
-	he->BW        = 1000 << RPC2_BW_SHIFT;
-	he->BWVar     = 0 << RPC2_BWVAR_SHIFT;
-	he->LastBytes = 0;
+	he->BR        = 1000 << RPC2_BR_SHIFT;
+	he->BRVar     = 0;
 
 	/* insert into hash table */
 	bucket = HASHHOST(&he->Host);
@@ -302,7 +301,8 @@
     rpc2_UpdateEstimates(host, &tv, Bytes);
 }
 
-/* Here we update the RTT and Bandwidth estimates,
+/* Here we update the RTT and Bandwidth (or more precise byterate in ns per
+ * byte) estimates,
  * ElapsedTime  is the observed roundtrip-time in milliseconds
  * Bytes        is the number of bytes transferred */
 void rpc2_UpdateEstimates(struct HEntry *host, struct timeval *elapsed,
@@ -310,7 +310,7 @@
 {
     unsigned long  elapsed_us;
     long	   eRTT;     /* estimated null roundtrip time */
-    long	   eBW;      /* estimated bandwidth */
+    long	   eBR;      /* estimated byterate (ns/B) */
     unsigned long  eU;       /* temporary unsigned variable */
     long	   eL;       /* temporary signed variable */
 
@@ -332,41 +332,38 @@
     /* get the estimated rtt */
     eRTT = host->RTT >> RPC2_RTT_SHIFT;
 
-    if (elapsed_us > eRTT)
-    {
-	eU  = elapsed_us - eRTT;
-
-	/* eBW = ( eU * 1000 ) / Bytes ; */
-	eBW = ((eU << 7) / Bytes) << 3;
+    if (elapsed_us > eRTT) eU = elapsed_us - eRTT;
+    else		   eU = 0;
 
-	/* This is a hack to compensate for slow WinNT servers */
-	/* HACK! to avoid small packets with unusually long RTT's to have a
-	 * negative effect on the BW estimate, we avoid using measurements
-	 * from small packets with a BW smaller than 1/2 the estimated BW */
-	if (eBW > (host->BW >> (RPC2_BW_SHIFT - 1)) && Bytes < 512) eBW = 0;
-	else eBW -= (host->BW >> RPC2_BW_SHIFT);
-	/* HACK! */
+    /* eBR = ( eU * 1000 ) / Bytes ; */
+    eBR = ((eU << 7) / Bytes) << 3;
+    eBR -= (host->BR >> RPC2_BR_SHIFT);
+
+    /* HACK! to avoid small packets with RTT's that are not within the current
+     * window of variance to have a strong effect on the byterate estimate, we
+     * halve the difference of the new measurement, if it falls outside of the
+     * variance window */
+    if      (eBR >  (host->BRVar >> RPC2_BRVAR_SHIFT)) eBR >>= 1;
+    else if (eBR < -(host->BRVar >> RPC2_BRVAR_SHIFT)) eBR >>= 1;
+    /* HACK! */
+
+    host->BR += eBR;
 
-	host->BW += eBW;
-
-	if (eBW < 0) eBW = -eBW;
-    }
-    else eBW = 0;
+    if (eBR < 0) eBR = -eBR;
 
-    /* Invariant: eBW contains the absolute difference between the previous
-     * calculated bandwidth and the new measurement */
+    /* Invariant: eBR contains the absolute difference between the previous
+     * calculated byterate and the new measurement */
 
-    eBW -= (host->BWVar >> RPC2_BWVAR_SHIFT);
-    host->BWVar += eBW;
+    eBR -= (host->BRVar >> RPC2_BRVAR_SHIFT);
+    host->BRVar += eBR;
 
     /* get a new RTT estimate in elapsed_us */
-    /* from here on eBW contains a lower estimate on the effective
-     * bandwidth, eRTT will contain a updated RTT estimate */
-    eBW = (host->BW >> RPC2_BW_SHIFT) +
-	((host->BWVar >> RPC2_BWVAR_SHIFT) >> 1);
+    /* from here on eBR contains a lower estimate on the effective
+     * byterate, eRTT will contain a updated RTT estimate */
+    eBR = (host->BR >> RPC2_BR_SHIFT) + ((host->BR >> RPC2_BRVAR_SHIFT) >> 1);
 
-    /* eU = ( eBW * Bytes ) / 1000 ; */
-    eU = ((eBW >> 3) * Bytes) >> 7;
+    /* eU = ( eBR * Bytes ) / 1000 ; */
+    eU = ((eBR >> 4) * Bytes) >> 6;
 
     if (elapsed_us > eU) eL = elapsed_us - eU;
     else		 eL = 0;
@@ -381,13 +378,11 @@
     eL -= (host->RTTVar >> RPC2_RTTVAR_SHIFT);
     host->RTTVar += eL;
 
-    host->LastBytes = Bytes;
-
     say(0, RPC2_DebugLevel,
-	"Est: %s %4ld.%06lu/%-5lu RTT:%lu/%lu us BW:%lu/%lu B/s\n",
+	"Est: %s %4ld.%06lu/%-5lu RTT:%lu/%lu us BR:%lu/%lu ns/B\n",
 	    inet_ntoa(host->Host), elapsed->tv_sec, elapsed->tv_usec, Bytes,
 	    host->RTT>>RPC2_RTT_SHIFT, host->RTTVar>>RPC2_RTTVAR_SHIFT,
-	    (1<<30)/(host->BW>>RPC2_BW_SHIFT), host->BWVar>>RPC2_BWVAR_SHIFT);
+	    (host->BR>>RPC2_BR_SHIFT), host->BRVar>>RPC2_BRVAR_SHIFT);
 
     return;
 }
@@ -396,7 +391,7 @@
 			struct timeval *tv)
 {
     unsigned long rto;
-    long          effBW;
+    long          effBR;
     int           i, shift = 1;
 
     if (!host || !tv) return;
@@ -413,11 +408,11 @@
      * RTT estimate (it is latency estimate), we have to add in the time to
      * send our packet into the estimated RTO */
 
-    effBW = (host->BW >> RPC2_BW_SHIFT);
-    // - ((host->BWVar >> RPC2_BWVAR_SHIFT) >> 1);
+    effBR = (host->BR >> RPC2_BR_SHIFT);
+    // - ((host->BRVar >> RPC2_BRVAR_SHIFT) >> 1);
 
-    /* rto += ( effBW * Bytes ) / 1000 ; */
-    rto += ((effBW >> 3) * Bytes) >> 7;
+    /* rto += ( effBR * Bytes ) / 1000 ; */
+    rto += ((effBR >> 3) * Bytes) >> 7;
     
     /* minimum bound for rtt estimates to compensate for scheduling etc. */
     if (rto < RPC2_MINRTO) rto = RPC2_MINRTO;
@@ -446,18 +441,40 @@
     return(RPC2_SUCCESS);
 }
 
-int RPC2_GetBandwidth(RPC2_Handle handle, unsigned long *BW,
-		      unsigned long *BWvar)
+int RPC2_GetBandwidth(RPC2_Handle handle, unsigned long *BWlow,
+		      unsigned long *BWavg, unsigned long *BWhigh)
 {
     struct CEntry *ce;
+    unsigned long BR, BRVar, tBR;
 
     ce = rpc2_GetConn(handle);
-    if (ce == NULL) 
-	return(RPC2_NOCONNECTION);
+    if (ce == NULL) return(RPC2_NOCONNECTION);
 
-    /* Adding 1 to the BW to avoid divide by zero errors --JH */
-    if (BW)    *BW    = 1000000000 / ((ce->HostInfo->BW >> RPC2_BW_SHIFT) + 1);
-    if (BWvar) *BWvar = ce->HostInfo->BWVar >> RPC2_BWVAR_SHIFT;
+    BR    = ce->HostInfo->BR    >> RPC2_BR_SHIFT;
+    BRVar = ce->HostInfo->BRVar >> RPC2_BRVAR_SHIFT;
+
+    if (BWlow) {
+	tBR = BR + BRVar;
+	/* Need at least 1 to avoid divide by zero errors --JH */
+	if (!tBR) tBR = 1;
+
+	*BWlow = 1000000000 / tBR;
+    }
+    if (BWavg) {
+	tBR = BR;
+	/* Need at least 1 to avoid divide by zero errors --JH */
+	if (!tBR) tBR = 1;
+
+	*BWavg = 1000000000 / tBR;
+    }
+    if (BWhigh) {
+	if (BR > BRVar)
+	    tBR = BR - BRVar;
+	else
+	    tBR = 1;
+
+	*BWhigh = 1000000000 / tBR;
+    }
 
     return(RPC2_SUCCESS);
 }
