timesync: make poll interval configurable

This adds PollIntervalMinSec= and PollIntervalMaxSec= to timesyncd.conf

Closes #7262.
This commit is contained in:
Yu Watanabe 2017-11-08 01:47:38 +09:00
parent 0b97f52a33
commit a4465d0d4c
6 changed files with 59 additions and 23 deletions

View file

@ -103,10 +103,21 @@
<varlistentry>
<term><varname>RootDistanceMaxSec=</varname></term>
<listitem><para>Maximum acceptable root distance in seconds.
<listitem><para>Maximum acceptable root distance. Takes a time value (in seconds).
Defaults to 5 seconds.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>PollIntervalMinSec=</varname></term>
<term><varname>PollIntervalMaxSec=</varname></term>
<listitem><para>The minimum and maximum poll intervals for NTP messages.
Each setting takes a time value (in seconds).
<varname>PollIntervalMinSec=</varname> must not be smaller than 16 seconds.
<varname>PollIntervalMaxSec=</varname> must be larger than <varname>PollIntervalMinSec=</varname>.
<varname>PollIntervalMinSec=</varname> defaults to 32 seconds, and
<varname>PollIntervalMaxSec=</varname> defaults to 2048 seconds.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View file

@ -106,11 +106,27 @@ int config_parse_servers(
}
int manager_parse_config_file(Manager *m) {
int r;
assert(m);
return config_parse_many_nulstr(PKGSYSCONFDIR "/timesyncd.conf",
CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"),
"Time\0",
config_item_perf_lookup, timesyncd_gperf_lookup,
false, m);
r = config_parse_many_nulstr(PKGSYSCONFDIR "/timesyncd.conf",
CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"),
"Time\0",
config_item_perf_lookup, timesyncd_gperf_lookup,
false, m);
if (r < 0)
return r;
if (m->poll_interval_min_usec < 16 * USEC_PER_SEC) {
log_warning("Invalid PollIntervalMinSec=. Using default value.");
m->poll_interval_min_usec = NTP_POLL_INTERVAL_MIN_USEC;
}
if (m->poll_interval_max_usec < m->poll_interval_min_usec) {
log_warning("PollIntervalMaxSec= is smaller than PollIntervalMinSec=. Using default value.");
m->poll_interval_max_usec = MAX(NTP_POLL_INTERVAL_MAX_USEC, m->poll_interval_min_usec * 32);
}
return r;
}

View file

@ -18,3 +18,5 @@ Time.NTP, config_parse_servers, SERVER_SYSTEM, 0
Time.Servers, config_parse_servers, SERVER_SYSTEM, 0
Time.FallbackNTP, config_parse_servers, SERVER_FALLBACK, 0
Time.RootDistanceMaxSec, config_parse_sec, 0, offsetof(Manager, max_root_distance_usec)
Time.PollIntervalMinSec, config_parse_sec, 0, offsetof(Manager, poll_interval_min_usec)
Time.PollIntervalMaxSec, config_parse_sec, 0, offsetof(Manager, poll_interval_max_usec)

View file

@ -55,16 +55,9 @@
/* expected accuracy of time synchronization; used to adjust the poll interval */
#define NTP_ACCURACY_SEC 0.2
/*
* "A client MUST NOT under any conditions use a poll interval less
* than 15 seconds."
*/
#define NTP_POLL_INTERVAL_MIN_SEC 32
#define NTP_POLL_INTERVAL_MAX_SEC 2048
/*
* Maximum delta in seconds which the system clock is gradually adjusted
* (slew) to approach the network time. Deltas larger that this are set by
* (slewed) to approach the network time. Deltas larger that this are set by
* letting the system time jump. The kernel's limit for adjtime is 0.5s.
*/
#define NTP_MAX_ADJUST 0.4
@ -80,7 +73,7 @@
#define NTP_FIELD_MODE(f) ((f) & 7)
#define NTP_FIELD(l, v, m) (((l) << 6) | ((v) << 3) | (m))
/* Maximum acceptable root distance in microseconds. */
/* Default of maximum acceptable root distance in microseconds. */
#define NTP_MAX_ROOT_DISTANCE (5 * USEC_PER_SEC)
/* Maximum number of missed replies before selecting another source. */
@ -204,10 +197,10 @@ static int manager_send_request(Manager *m) {
/* re-arm timer with increasing timeout, in case the packets never arrive back */
if (m->retry_interval > 0) {
if (m->retry_interval < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
if (m->retry_interval < m->poll_interval_max_usec)
m->retry_interval *= 2;
} else
m->retry_interval = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
m->retry_interval = m->poll_interval_min_usec;
r = manager_arm_timer(m, m->retry_interval);
if (r < 0)
@ -446,27 +439,27 @@ static void manager_adjust_poll(Manager *m, double offset, bool spike) {
assert(m);
if (m->poll_resync) {
m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
m->poll_interval_usec = m->poll_interval_min_usec;
m->poll_resync = false;
return;
}
/* set to minimal poll interval */
if (!spike && fabs(offset) > NTP_ACCURACY_SEC) {
m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
m->poll_interval_usec = m->poll_interval_min_usec;
return;
}
/* increase polling interval */
if (fabs(offset) < NTP_ACCURACY_SEC * 0.25) {
if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
if (m->poll_interval_usec < m->poll_interval_max_usec)
m->poll_interval_usec *= 2;
return;
}
/* decrease polling interval */
if (spike || fabs(offset) > NTP_ACCURACY_SEC * 0.75) {
if (m->poll_interval_usec > NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC)
if (m->poll_interval_usec > m->poll_interval_min_usec)
m->poll_interval_usec /= 2;
return;
}
@ -743,7 +736,7 @@ static int manager_begin(Manager *m) {
m->good = false;
m->missed_replies = NTP_MAX_MISSED_REPLIES;
if (m->poll_interval_usec == 0)
m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
m->poll_interval_usec = m->poll_interval_min_usec;
server_address_pretty(m->current_server_address, &pretty);
log_debug("Connecting to time server %s (%s).", strna(pretty), m->current_server_name->string);
@ -921,7 +914,7 @@ int manager_connect(Manager *m) {
m->exhausted_servers = true;
/* Increase the polling interval */
if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
if (m->poll_interval_usec < m->poll_interval_max_usec)
m->poll_interval_usec *= 2;
return 0;
@ -1125,6 +1118,8 @@ int manager_new(Manager **ret) {
return -ENOMEM;
m->max_root_distance_usec = NTP_MAX_ROOT_DISTANCE;
m->poll_interval_min_usec = NTP_POLL_INTERVAL_MIN_USEC;
m->poll_interval_max_usec = NTP_POLL_INTERVAL_MAX_USEC;
m->server_socket = m->clock_watch_fd = -1;

View file

@ -25,11 +25,19 @@
#include "list.h"
#include "ratelimit.h"
#include "time-util.h"
typedef struct Manager Manager;
#include "timesyncd-server.h"
/*
* "A client MUST NOT under any conditions use a poll interval less
* than 15 seconds."
*/
#define NTP_POLL_INTERVAL_MIN_USEC (32 * USEC_PER_SEC)
#define NTP_POLL_INTERVAL_MAX_USEC (2048 * USEC_PER_SEC)
struct Manager {
sd_event *event;
sd_resolve *resolve;
@ -67,6 +75,8 @@ struct Manager {
/* poll timer */
sd_event_source *event_timer;
usec_t poll_interval_usec;
usec_t poll_interval_min_usec;
usec_t poll_interval_max_usec;
bool poll_resync;
/* history data */

View file

@ -15,3 +15,5 @@
#NTP=
#FallbackNTP=@NTP_SERVERS@
#RootDistanceMaxSec=5
#PollIntervalMinSec=32
#PollIntervalMaxSec=2048