--- libmetrics/linux/metrics.c-ori	2008-09-09 18:54:40.000000000 +0000
+++ libmetrics/linux/metrics.c	2008-09-11 13:44:49.000000000 +0000
@@ -57,6 +57,8 @@
 timely_file proc_meminfo = { {0,0} , 5., "/proc/meminfo" };
 timely_file proc_net_dev = { {0,0} , 1., "/proc/net/dev" };
 
+static unsigned long counterdiff(unsigned long, unsigned long, unsigned long, unsigned long);
+
 float timediff(const struct timeval *thistime, const struct timeval *lasttime)
 {
   float diff;
@@ -222,40 +224,20 @@
 		     if ( !ns ) return;
 
 		     rbi = strtoul( p, &p ,10);
-		     if ( rbi >= ns->rbi ) {
-			l_bytes_in += rbi - ns->rbi;
-		     } else {
-			debug_msg("update_ifdata(%s) - Overflow in rbi: %lu -> %lu",caller,ns->rbi,rbi);
-			l_bytes_in += ULONG_MAX - ns->rbi + rbi;
-		     }
+		     l_bytes_in += counterdiff(rbi,ns->rbi,ULONG_MAX, 0);
 		     ns->rbi = rbi;
 
 		     rpi = strtoul( p, &p ,10);
-		     if ( rpi >= ns->rpi ) {
-			l_pkts_in += rpi - ns->rpi;
-		     } else {
-			debug_msg("updata_ifdata(%s) - Overflow in rpi: %lu -> %lu",caller,ns->rpi,rpi);
-			l_pkts_in += ULONG_MAX - ns->rpi + rpi;
-		     }
+		     l_pkts_in += counterdiff(rpi,ns->rpi,ULONG_MAX, 0);
 		     ns->rpi = rpi;
 
 		     for (i = 0; i < 6; i++) strtol(p, &p, 10);
 		     rbo = strtoul( p, &p ,10);
-		     if ( rbo >= ns->rbo ) {
-			l_bytes_out += rbo - ns->rbo;
-		     } else {
-			debug_msg("update_ifdata(%s) - Overflow in rbo: %lu -> %lu",caller,ns->rbo,rbo);
-			l_bytes_out += ULONG_MAX - ns->rbo + rbo;
-		     }
+		     l_bytes_out += counterdiff(rbo,ns->rbo,ULONG_MAX, 0);
 		     ns->rbo = rbo;
 
 		     rpo = strtoul( p, &p ,10);
-		     if ( rpo >= ns->rpo ) {
-			l_pkts_out += rpo - ns->rpo;
-		     } else {
-			debug_msg("update_ifdata(%s) - Overflow in rpo: %lu -> %lu",caller,ns->rpo,rpo);
-			l_pkts_out += ULONG_MAX - ns->rpo + rpo;
-		     }
+		     l_pkts_out += counterdiff(rpo,ns->rpo,ULONG_MAX, 0);
 		     ns->rpo = rpo;
 		  }
 	       p = index (p, '\n') + 1;    // skips a line
@@ -1305,3 +1287,40 @@
    val.f = most_full;
    return val;
 }
+
+static unsigned long
+counterdiff(unsigned long oldval, unsigned long newval, unsigned long maxval, unsigned long maxdiff)
+{
+	unsigned long diff;
+
+	if (maxdiff == 0)
+		maxdiff = maxval;
+
+	/* Paranoia */
+	if (oldval > maxval || newval > maxval)
+		return 0;
+
+	/*
+	 * Tackle the easy case.  Don't worry about maxdiff here because
+	 * we're SOL if it happens (i.e. assuming a reset just makes
+	 * matters worse).
+	 */
+	if (oldval <= newval)
+		return (newval - oldval);
+
+	/*
+	 * Now the tricky part.  If we assume counters never get reset,
+	 * this is easy.  Unfortunaly, they do get reset on some
+	 * systems, so we need to try and deal with that.  Our huristic
+	 * is that if out difference is greater then maxdiff and newval
+	 * is less or equal to maxdiff, then we've probably been reset
+	 * rather then actually wrapping.  Obviously, you need to be
+	 * careful to poll often enough that you won't exceed maxdiff or
+	 * you will get undersized numbers when you do wrap.
+	 */
+	diff = maxval - oldval + newval;
+	if (diff > maxdiff && newval <= maxdiff)
+		return newval;
+
+	return diff;
+}
