--- include/utils.h
+++ include/utils.h	2011/01/05 13:18:30
@@ -79,6 +79,7 @@ extern int mask2bits(__u32 netmask);
 extern int get_integer(int *val, const char *arg, int base);
 extern int get_unsigned(unsigned *val, const char *arg, int base);
 extern int get_jiffies(unsigned *val, const char *arg, int base, int *raw);
+extern int get_time_in_units(unsigned *val, const char *arg, int base, int *raw, unsigned unit);
 #define get_byte get_u8
 #define get_ushort get_u16
 #define get_short get_s16
--- ip/iproute.c
+++ ip/iproute.c	2011/01/05 13:42:17
@@ -37,6 +37,19 @@
 #define RTAX_RTTVAR RTAX_HOPS
 #endif
 
+#define TIME_UNIT_MS 1000
+static unsigned get_rto_min_units(void)
+{
+	/*
+	 * recent kernels (>=2.6.27 ?) are using milliseconds base.
+	 * Note: To support older kernels, return the proper HZ...
+	 *
+	 * final unit for rto_min: unit
+	 *                rttvar:  unit * 4
+	 *                rtt:     unit * 8
+	 */
+	return TIME_UNIT_MS;
+}
 
 static const char *mx_names[RTAX_MAX+1] = {
 	[RTAX_MTU]	= "mtu",
@@ -493,12 +506,11 @@ int print_route(const struct sockaddr_nl
 			mxlock = *(unsigned*)RTA_DATA(mxrta[RTAX_LOCK]);
 
 		for (i=2; i<= RTAX_MAX; i++) {
-			unsigned val;
+			unsigned long long val;
+			unsigned unit = get_rto_min_units();
 
 			if (mxrta[i] == NULL)
 				continue;
-			if (!hz)
-				hz = get_hz();
 
 			if (i < sizeof(mx_names)/sizeof(char*) && mx_names[i])
 				fprintf(fp, " %s", mx_names[i]);
@@ -510,28 +522,28 @@ int print_route(const struct sockaddr_nl
 			val = *(unsigned*)RTA_DATA(mxrta[i]);
 			switch (i) {
 			case RTAX_HOPLIMIT:
-				if ((long)val == -1)
+				if ((int)val == -1)
 					val = 0;
 				/* fall through */
 			default:
-				fprintf(fp, " %u", val);
+				fprintf(fp, " %u", (unsigned)val);
 				break;
 
 			case RTAX_RTT:
 			case RTAX_RTTVAR:
 			case RTAX_RTO_MIN:
-				val *= 1000;
+				val *= TIME_UNIT_MS;
 				if (i == RTAX_RTT)
 					val /= 8;
 				else if (i == RTAX_RTTVAR)
 					val /= 4;
 
-				if (val >= hz)
+				if (val >= unit)
 					fprintf(fp, " %llums",
-						(unsigned long long) val / hz);
+						val / unit);
 				else
-					fprintf(fp, " %.2fms", 
-						(double)val / hz);
+					fprintf(fp, " %.8fms", 
+						(double)val / unit);
 			}
 		}
 	}
@@ -799,7 +811,7 @@ int iproute_modify(int cmd, unsigned fla
 				mxlock |= (1<<RTAX_RTT);
 				NEXT_ARG();
 			}
-			if (get_jiffies(&rtt, *argv, 0, &raw))
+			if (get_time_in_units(&rtt, *argv, 0, &raw, get_rto_min_units()))
 				invarg("\"rtt\" value is invalid\n", *argv);
 			rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTT, 
 				(raw) ? rtt : rtt * 8);
@@ -807,7 +819,7 @@ int iproute_modify(int cmd, unsigned fla
 			unsigned rto_min;
 			NEXT_ARG();
 			mxlock |= (1<<RTAX_RTO_MIN);
-			if (get_jiffies(&rto_min, *argv, 0, &raw))
+			if (get_time_in_units(&rto_min, *argv, 0, &raw, get_rto_min_units()))
 				invarg("\"rto_min\" value is invalid\n",
 				       *argv);
 			rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTO_MIN,
@@ -849,7 +861,7 @@ int iproute_modify(int cmd, unsigned fla
 				mxlock |= (1<<RTAX_RTTVAR);
 				NEXT_ARG();
 			}
-			if (get_jiffies(&win, *argv, 0, &raw))
+			if (get_time_in_units(&win, *argv, 0, &raw, get_rto_min_units()))
 				invarg("\"rttvar\" value is invalid\n", *argv);
 			rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTTVAR,
 				(raw) ? win : win * 4);
--- lib/utils.c
+++ lib/utils.c	2011/01/05 13:19:16
@@ -164,6 +164,60 @@ int get_jiffies(unsigned *jiffies, const
 
 }
 
+int get_time_in_units(unsigned *jiffies, const char *arg, int base, int *raw, unsigned unit)
+{
+	double t;
+	unsigned long res;
+	char *p;
+
+	if (strchr(arg,'.') != NULL) {
+		t = strtod(arg,&p);
+		if (t < 0.0)
+			return -1;
+	}
+	else {
+		res = strtoul(arg,&p,base);
+		if (res > UINT_MAX)
+			return -1;
+		t = (double)res;
+	}
+	if (p == arg)
+		return -1;
+
+	*raw = 1;
+
+	if (*p) {
+		*raw = 0;
+                if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 ||
+                    strcasecmp(p, "secs")==0)
+                        t *= unit;
+                else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 ||
+                         strcasecmp(p, "msecs") == 0)
+                        t *= unit/1000.0;
+                else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 ||
+                         strcasecmp(p, "usecs") == 0)
+                        t *= unit/1000000.0;
+                else if (strcasecmp(p, "ns") == 0 || strcasecmp(p, "nsec")==0 ||
+                         strcasecmp(p, "nsecs") == 0)
+                        t *= unit/1000000000.0;
+		else if (strcasecmp(p, "j") == 0 || strcasecmp(p, "hz") == 0 ||
+			 strcasecmp(p,"jiffies") == 0)
+			t *= unit/get_hz();
+                else
+                        return -1;
+        }
+
+	/* emulate ceil() without having to bring-in -lm and always be >= 1 */
+
+	*jiffies = t;
+	if (*jiffies < t)
+		*jiffies += 1;
+	
+        return 0;
+
+}
+
+
 int get_u64(__u64 *val, const char *arg, int base)
 {
 	unsigned long long res;
