diff --git a/broadcast.c b/broadcast.c index 4005ba6..17c0934 100644 --- a/broadcast.c +++ b/broadcast.c @@ -121,7 +121,7 @@ timeout_handler(void *arbitrary) /* 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); @@ -148,7 +148,7 @@ BRD_AddDestination(IPAddr *addr, unsigned short port, int interval) 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)); diff --git a/ntp_core.c b/ntp_core.c index 909f720..d87510e 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -178,6 +178,9 @@ struct NCR_Instance_Record { 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 @@ -247,6 +250,7 @@ start_initial_timeout(NCR_Instance inst) /* 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; @@ -622,6 +626,7 @@ transmit_timeout(void *arg) /* Requeue timeout */ inst->timer_running = 1; inst->timeout_id = SCH_AddTimeoutInClass(WARM_UP_DELAY, SAMPLING_SEPARATION, + SAMPLING_RANDOMNESS, SCH_NtpSamplingClass, transmit_timeout, (void *)inst); @@ -707,6 +712,7 @@ transmit_timeout(void *arg) 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 { @@ -1259,6 +1265,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins /* 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); } @@ -1818,6 +1825,7 @@ NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_sampl } inst->timer_running = 1; inst->timeout_id = SCH_AddTimeoutInClass(0.0, SAMPLING_SEPARATION, + SAMPLING_RANDOMNESS, SCH_NtpSamplingClass, transmit_timeout, (void *) inst); break; @@ -1831,6 +1839,7 @@ NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_sampl } inst->timer_running = 1; inst->timeout_id = SCH_AddTimeoutInClass(0.0, SAMPLING_SEPARATION, + SAMPLING_RANDOMNESS, SCH_NtpSamplingClass, transmit_timeout, (void *) inst); break; diff --git a/sched.c b/sched.c index 369b03e..cd6cf78 100644 --- a/sched.c +++ b/sched.c @@ -129,6 +129,7 @@ handle_slew(struct timeval *raw, void SCH_Initialise(void) { + struct timeval tv; FD_ZERO(&read_fds); n_read_fds = 0; @@ -143,6 +144,9 @@ SCH_Initialise(void) LCL_AddParameterChangeHandler(handle_slew, NULL); + LCL_ReadRawTime(&tv); + srandom(tv.tv_sec * tv.tv_usec); + initialised = 1; return; @@ -322,17 +326,23 @@ SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler handler, SCH_ArbitraryArg /* ================================================== */ 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; diff --git a/sched.h b/sched.h index 143c4c3..d134c86 100644 --- a/sched.h +++ b/sched.h @@ -72,8 +72,9 @@ extern SCH_TimeoutID SCH_AddTimeoutByDelay(double delay, SCH_TimeoutHandler, SCH /* 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);