dccp ccid-3: Runtime verification of timer resolution
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>
This commit is contained in:
parent
7d1af6a8d9
commit
f76fd327a8
3 changed files with 18 additions and 3 deletions
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue