dccp ccid-3: Runtime verification of timer resolution
authorGerrit Renker <gerrit@erg.abdn.ac.uk>
Thu, 4 Sep 2008 05:30:19 +0000 (07:30 +0200)
committerGerrit Renker <gerrit@erg.abdn.ac.uk>
Thu, 4 Sep 2008 05:45:40 +0000 (07:45 +0200)
The DCCP base time resolution is 10 microseconds (RFC 4340, 13.1 ... 13.3).

Using a timer with a lower resolution was found to trigger the following
bug warnings/problems on high-speed networks (e.g. local loopback):
 * RTT samples are rounded down to 0 if below resolution;
 * in some cases, negative RTT samples were observed;
 * the CCID-3 feedback timer complains that the feedback interval is 0,
   since the feedback interval is in the order of 1 RTT or less and RTT
   measurement rounded this down to 0;
On an Intel computer this will for instance happen when using a
boot-time parameter of "clocksource=jiffies".

The following system log messages were observed:
  11:24:00 kernel: BUG: delta (0) <= 0 at ccid3_hc_rx_send_feedback()
  11:26:12 kernel: BUG: delta (0) <= 0 at ccid3_hc_rx_send_feedback()
  11:26:30 kernel: dccp_sample_rtt: unusable RTT sample 0, using min
  11:26:30 last message repeated 5 times

This patch defines a global constant for the time resolution, adds this in
timer.c, and checks the available clock resolution at CCID-3 module load time.

When the resolution is worse than 10 microseconds, module loading exits with
a message "socket type not supported".

Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
net/dccp/ccids/ccid3.c
net/dccp/dccp.h
net/dccp/timer.c

index 0d406f8..f566eb7 100644 (file)
@@ -869,6 +869,19 @@ MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
 
 static __init int ccid3_module_init(void)
 {
+       struct timespec tp;
+
+       /*
+        * Without a fine-grained clock resolution, RTTs/X_recv are not sampled
+        * correctly and feedback is sent either too early or too late.
+        */
+       hrtimer_get_res(CLOCK_MONOTONIC, &tp);
+       if (tp.tv_sec || tp.tv_nsec > DCCP_TIME_RESOLUTION * NSEC_PER_USEC) {
+               printk(KERN_ERR "%s: Timer too coarse (%ld usec), need %u-usec"
+                      " resolution - check your clocksource.\n", __func__,
+                      tp.tv_nsec/NSEC_PER_USEC, DCCP_TIME_RESOLUTION);
+               return -ESOCKTNOSUPPORT;
+       }
        return ccid_register(&ccid3);
 }
 module_init(ccid3_module_init);
index 1585fa2..b63a82c 100644 (file)
@@ -86,10 +86,13 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
  */
 #define DCCP_RTO_MAX ((unsigned)(64 * HZ))
 
+/* DCCP base time resolution - 10 microseconds (RFC 4340, 13.1 ... 13.3) */
+#define DCCP_TIME_RESOLUTION   10
+
 /*
  * RTT sampling: sanity bounds and fallback RTT value from RFC 4340, section 3.4
  */
-#define DCCP_SANE_RTT_MIN      100
+#define DCCP_SANE_RTT_MIN      (10 * DCCP_TIME_RESOLUTION)
 #define DCCP_FALLBACK_RTT      (USEC_PER_SEC / 5)
 #define DCCP_SANE_RTT_MAX      (3 * USEC_PER_SEC)
 
index e02d5a9..16359e2 100644 (file)
@@ -281,8 +281,7 @@ u32 dccp_timestamp(void)
 {
        s64 delta = ktime_us_delta(ktime_get_real(), dccp_timestamp_seed);
 
-       do_div(delta, 10);
-       return delta;
+       return div_u64(delta, DCCP_TIME_RESOLUTION);
 }
 EXPORT_SYMBOL_GPL(dccp_timestamp);