diff --git a/conf.c b/conf.c index 682b971..b7c3ddc 100644 --- a/conf.c +++ b/conf.c @@ -85,6 +85,7 @@ static char *rtc_file = NULL; static double max_update_skew = 1000.0; static double correction_time_ratio = 3.0; static double max_clock_error = 1.0; /* in ppm */ +static double max_drift = 500000.0; /* in ppm */ static double max_slew_rate = 1e6 / 12.0; /* in ppm */ static double max_distance = 3.0; @@ -489,6 +490,8 @@ CNF_ParseLine(const char *filename, int number, char *line) parse_double(p, &max_clock_error); } else if (!strcasecmp(command, "maxdistance")) { parse_double(p, &max_distance); + } else if (!strcasecmp(command, "maxdrift")) { + parse_double(p, &max_drift); } else if (!strcasecmp(command, "maxsamples")) { parse_int(p, &max_samples); } else if (!strcasecmp(command, "maxslewrate")) { @@ -1486,6 +1489,14 @@ CNF_GetMaxUpdateSkew(void) /* ================================================== */ +double +CNF_GetMaxDrift(void) +{ + return max_drift; +} + +/* ================================================== */ + double CNF_GetMaxClockError(void) { diff --git a/conf.h b/conf.h index b5ac5cf..34c7e41 100644 --- a/conf.h +++ b/conf.h @@ -83,6 +83,7 @@ extern char *CNF_GetLeapSecTimezone(void); /* Value returned in ppm, as read from file */ extern double CNF_GetMaxUpdateSkew(void); extern double CNF_GetMaxClockError(void); +extern double CNF_GetMaxDrift(void); extern double CNF_GetCorrectionTimeRatio(void); extern double CNF_GetMaxSlewRate(void); diff --git a/doc/chrony.conf.adoc b/doc/chrony.conf.adoc index 55d20ca..bd44b90 100644 --- a/doc/chrony.conf.adoc +++ b/doc/chrony.conf.adoc @@ -805,6 +805,16 @@ By default, the maximum error is 1 ppm. Typical values for _error-in-ppm_ might be 10 for a low quality clock and 0.1 for a high quality clock using a temperature compensated crystal oscillator. +[[maxdrift]]*maxdrift* _drift-in-ppm_:: +This directive specifies the maximum assumed drift (frequency error) of the +system clock. It limits the frequency adjustment that *chronyd* is allowed to +use to correct the measured drift. It is an additional limit to the maximum +adjustment that can be set by the system driver (100000 ppm on Linux, 500 ppm +on FreeBSD and NetBSD, 32500 ppm on Solaris). ++ +By default, the maximum assumed drift is 500000 ppm, i.e. the adjustment is +limited by the system driver rather than this directive. + [[maxupdateskew]]*maxupdateskew* _skew-in-ppm_:: One of *chronyd*'s tasks is to work out how fast or slow the computer's clock runs relative to its reference sources. In addition, it computes an estimate of diff --git a/local.c b/local.c index 848cc3e..2ec173e 100644 --- a/local.c +++ b/local.c @@ -42,13 +42,12 @@ /* ================================================== */ -/* Maximum allowed frequency offset in ppm, the time must not stop - or run backwards */ -#define MAX_FREQ 500000.0 - /* Variable to store the current frequency, in ppm */ static double current_freq_ppm; +/* Maximum allowed frequency, in ppm */ +static double max_freq_ppm; + /* Temperature compensation, in ppm */ static double temp_comp_ppm; @@ -166,6 +165,11 @@ LCL_Initialise(void) calculate_sys_precision(); + /* This is the maximum allowed frequency offset in ppm, the time must + never stop or run backwards */ + max_freq_ppm = CNF_GetMaxDrift(); + max_freq_ppm = CLAMP(0.0, max_freq_ppm, 500000.0); + max_clock_error = CNF_GetMaxClockError() * 1e-6; } @@ -406,12 +410,12 @@ LCL_ReadAbsoluteFrequency(void) static double clamp_freq(double freq) { - if (freq <= MAX_FREQ && freq >= -MAX_FREQ) + if (freq <= max_freq_ppm && freq >= -max_freq_ppm) return freq; LOG(LOGS_WARN, LOGF_Local, "Frequency %.1f ppm exceeds allowed maximum", freq); - return freq >= MAX_FREQ ? MAX_FREQ : -MAX_FREQ; + return CLAMP(-max_freq_ppm, freq, max_freq_ppm); } /* ================================================== */