ntp: add server time smoothing

Time smoothing determines an offset that needs to be applied to the
cooked time to make it smooth for external observers. Observed offset
and frequency change slowly and there are no discontinuities. This can
be used on an NTP server to make it easier for the clients to track the
time and keep their clocks close together even when large offset or
frequency corrections are applied to the server's clock (e.g. after
being offline for longer time).

Accumulated offset and frequency are smoothed out in three stages. In
the first stage, the frequency is changed at a constant rate (wander) up
to a maximum, in the second stage the frequency stays at the maximum for
as long as needed and in the third stage the frequency is brought back
to zero.

Time smoothing is configured by the smoothtime directive. It takes two
arguments, maximum frequency offset and maximum wander. It's disabled by
default.
This commit is contained in:
Miroslav Lichvar
2015-03-31 15:47:11 +02:00
parent 78283dd822
commit 7f45eb7957
11 changed files with 381 additions and 6 deletions

27
conf.c
View File

@@ -73,6 +73,7 @@ static void parse_peer(char *);
static void parse_pool(char *);
static void parse_refclock(char *);
static void parse_server(char *);
static void parse_smoothtime(char *);
static void parse_tempcomp(char *);
/* ================================================== */
@@ -185,6 +186,10 @@ static IPAddr bind_cmd_address4, bind_cmd_address6;
* chronyds being started. */
static char *pidfile;
/* Smoothing constants */
static double smooth_max_freq = 0.0; /* in ppm */
static double smooth_max_wander = 0.0; /* in ppm/s */
/* Temperature sensor, update interval and compensation coefficients */
static char *tempcomp_sensor_file = NULL;
static char *tempcomp_point_file = NULL;
@@ -512,6 +517,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
parse_int(p, &sched_priority);
} else if (!strcasecmp(command, "server")) {
parse_server(p);
} else if (!strcasecmp(command, "smoothtime")) {
parse_smoothtime(p);
} else if (!strcasecmp(command, "stratumweight")) {
parse_double(p, &stratum_weight);
} else if (!strcasecmp(command, "tempcomp")) {
@@ -1164,6 +1171,17 @@ parse_broadcast(char *line)
/* ================================================== */
static void
parse_smoothtime(char *line)
{
check_number_of_args(line, 2);
if (sscanf(line, "%lf %lf", &smooth_max_freq, &smooth_max_wander) != 2) {
smooth_max_freq = 0.0;
command_parse_error();
}
}
/* ================================================== */
static void
parse_tempcomp(char *line)
{
@@ -1719,6 +1737,15 @@ CNF_GetLockMemory(void)
/* ================================================== */
void
CNF_GetSmooth(double *max_freq, double *max_wander)
{
*max_freq = smooth_max_freq;
*max_wander = smooth_max_wander;
}
/* ================================================== */
void
CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2)
{