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.
This commit is contained in:
Miroslav Lichvar 2023-06-06 12:02:53 +02:00
parent ab8da7ecb9
commit b90d2c084f
2 changed files with 10 additions and 7 deletions

View file

@ -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);
}

View file

@ -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