/* Requeue timeout. Don't care if interval drifts gradually, so just do it
* at the end. */
- SCH_AddTimeoutInClass((double) d->interval, 1.0,
+ SCH_AddTimeoutInClass((double) d->interval, 1.0, 0.02,
SCH_NtpBroadcastClass,
timeout_handler, (void *) d);
destinations[n_destinations].addr.port = port;
destinations[n_destinations].interval = interval;
- SCH_AddTimeoutInClass((double) interval, 1.0,
+ SCH_AddTimeoutInClass((double) interval, 1.0, 0.0,
SCH_NtpBroadcastClass,
timeout_handler, (void *)(destinations + n_destinations));
minimise risk of network collisions) (in seconds) */
#define SAMPLING_SEPARATION 0.2
+/* Randomness added to spacing between samples for one server/peer */
+#define SAMPLING_RANDOMNESS 0.02
+
/* Spacing between samples in burst mode for one server/peer */
#define BURST_INTERVAL 2.0
/* Start timer for first transmission */
inst->timeout_id = SCH_AddTimeoutInClass(INITIAL_DELAY, SAMPLING_SEPARATION,
+ SAMPLING_RANDOMNESS,
SCH_NtpSamplingClass,
transmit_timeout, (void *)inst);
inst->timer_running = 1;
/* Requeue timeout */
inst->timer_running = 1;
inst->timeout_id = SCH_AddTimeoutInClass(WARM_UP_DELAY, SAMPLING_SEPARATION,
+ SAMPLING_RANDOMNESS,
SCH_NtpSamplingClass,
transmit_timeout, (void *)inst);
if (do_timer) {
inst->timer_running = 1;
inst->timeout_id = SCH_AddTimeoutInClass(timeout_delay, SAMPLING_SEPARATION,
+ SAMPLING_RANDOMNESS,
SCH_NtpSamplingClass,
transmit_timeout, (void *)inst);
} else {
/* Get rid of old timeout and start a new one */
SCH_RemoveTimeout(inst->timeout_id);
inst->timeout_id = SCH_AddTimeoutInClass(delay_time, SAMPLING_SEPARATION,
+ SAMPLING_RANDOMNESS,
SCH_NtpSamplingClass,
transmit_timeout, (void *)inst);
}
}
inst->timer_running = 1;
inst->timeout_id = SCH_AddTimeoutInClass(0.0, SAMPLING_SEPARATION,
+ SAMPLING_RANDOMNESS,
SCH_NtpSamplingClass,
transmit_timeout, (void *) inst);
break;
}
inst->timer_running = 1;
inst->timeout_id = SCH_AddTimeoutInClass(0.0, SAMPLING_SEPARATION,
+ SAMPLING_RANDOMNESS,
SCH_NtpSamplingClass,
transmit_timeout, (void *) inst);
break;
void
SCH_Initialise(void)
{
+ struct timeval tv;
FD_ZERO(&read_fds);
n_read_fds = 0;
LCL_AddParameterChangeHandler(handle_slew, NULL);
+ LCL_ReadRawTime(&tv);
+ srandom(tv.tv_sec * tv.tv_usec);
+
initialised = 1;
return;
/* ================================================== */
SCH_TimeoutID
-SCH_AddTimeoutInClass(double min_delay, double separation,
+SCH_AddTimeoutInClass(double min_delay, double separation, double randomness,
SCH_TimeoutClass class,
SCH_TimeoutHandler handler, SCH_ArbitraryArgument arg)
{
TimerQueueEntry *new_tqe;
TimerQueueEntry *ptr;
struct timeval now;
- double diff;
+ double diff, r;
double new_min_delay;
assert(initialised);
+
+ if (randomness > 0.0) {
+ r = random() % 0xffff / (0xffff - 1.0) * randomness + 1.0;
+ min_delay *= r;
+ separation *= r;
+ }
LCL_ReadRawTime(&now);
new_min_delay = min_delay;
/* This queues a timeout in a particular class, ensuring that the
expiry time is at least a given separation away from any other
- timeout in the same class */
-extern SCH_TimeoutID SCH_AddTimeoutInClass(double min_delay, double separation,
+ timeout in the same class, given randomness is added to the delay
+ and separation */
+extern SCH_TimeoutID SCH_AddTimeoutInClass(double min_delay, double separation, double randomness,
SCH_TimeoutClass class,
SCH_TimeoutHandler handler, SCH_ArbitraryArgument);