From b90d2c084fe9ee398fcb7b8e6e636508dbc51de3 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 6 Jun 2023 12:02:53 +0200 Subject: [PATCH] ntp: randomize replacement interval Replacement attempts are globally rate limited to one per 7*2^8 seconds to limit the rate of DNS requests for public servers like pool.ntp.org. If multiple sources are repeatedly attempting replacement (at their polling intervals), one source can be getting all attempts for periods of time. Use a randomly generated interval to randomize the order of source replacements without changing the average rate. --- ntp_sources.c | 13 ++++++++----- test/simulation/139-nts | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ntp_sources.c b/ntp_sources.c index 2f20299..152c418 100644 --- a/ntp_sources.c +++ b/ntp_sources.c @@ -106,7 +106,7 @@ struct UnresolvedSource { #define RESOLVE_INTERVAL_UNIT 7 #define MIN_RESOLVE_INTERVAL 2 #define MAX_RESOLVE_INTERVAL 9 -#define MIN_REPLACEMENT_INTERVAL 8 +#define MAX_REPLACEMENT_INTERVAL 9 static struct UnresolvedSource *unresolved_sources = NULL; static int resolving_interval = 0; @@ -1006,9 +1006,10 @@ resolve_source_replacement(SourceRecord *record, int refreshment) void NSR_HandleBadSource(IPAddr *address) { - static double last_replacement = -1e6; + static double next_replacement = 0.0; SourceRecord *record; IPAddr ip_addr; + uint32_t rnd; double now; int slot; @@ -1025,12 +1026,14 @@ NSR_HandleBadSource(IPAddr *address) /* Don't resolve names too frequently */ now = SCH_GetLastEventMonoTime(); - if (now - last_replacement < - RESOLVE_INTERVAL_UNIT * (1 << MIN_REPLACEMENT_INTERVAL)) { + if (now < next_replacement) { DEBUG_LOG("replacement postponed"); return; } - last_replacement = now; + + UTI_GetRandomBytes(&rnd, sizeof (rnd)); + next_replacement = now + ((double)rnd / (uint32_t)-1) * + (RESOLVE_INTERVAL_UNIT * (1 << MAX_REPLACEMENT_INTERVAL)); resolve_source_replacement(record, 0); } diff --git a/test/simulation/139-nts b/test/simulation/139-nts index 6a2112d..0cfb874 100755 --- a/test/simulation/139-nts +++ b/test/simulation/139-nts @@ -160,8 +160,8 @@ for dns in 1 0; do check_file_messages " 2 1 .* 4460 " 50 100 log.packets || test_fail check_file_messages " 2 2 .* 4460 " 0 0 log.packets || test_fail - check_log_messages "Source 192.168.123.1 changed to 192.168.123.2" 6 8 || test_fail - check_log_messages "Source 192.168.123.2 replaced with 192.168.123.1" 6 8 || test_fail + check_log_messages "Source 192.168.123.1 changed to 192.168.123.2" 4 10 || test_fail + check_log_messages "Source 192.168.123.2 replaced with 192.168.123.1" 4 10 || test_fail servers=2