diff --git a/chrony.texi b/chrony.texi index 47086aa..bee73f5 100644 --- a/chrony.texi +++ b/chrony.texi @@ -1191,6 +1191,7 @@ directives can occur in any order in the file. * mailonchange directive:: Send email if a clock correction above a threshold occurs * makestep directive:: Step system clock if large correction is needed * manual directive:: Allow manual entry using chronyc's settime cmd. +* maxclockerror directive:: Set maximum frequency error of local clock * maxupdateskew directive:: Stop bad estimates upsetting machine clock * noclientlog directive:: Prevent chronyd from gathering data about clients * clientloglimit directive:: Set client log memory limit @@ -2209,6 +2210,25 @@ idea of the two commands is that the @code{manual} command controls the manual clock driver's behaviour, whereas the @code{settime} command allows samples of manually entered time to be provided). @c }}} +@c {{{ maxclockerror +@node maxclockerror directive +@subsection maxclockerror +The @code{maxclockerror} directive sets the maximum assumed frequency +error of the local clock. This is a frequency stability of the clock, +not an absolute frequency error. + +By default, the maximum assumed error is set to 10 ppm. + +The syntax is + +@example +maxclockerror +@end example + +Typical values for might be 10 for a low quality clock +to 0.1 for a high quality clock using a temperature compensated +crystal oscillator. +@c }}} @c {{{ maxupdateskew @node maxupdateskew directive @subsection maxupdateskew diff --git a/conf.c b/conf.c index e4ed75a..f6fd9b2 100644 --- a/conf.c +++ b/conf.c @@ -77,6 +77,7 @@ static void parse_log(const char *); static void parse_logbanner(const char *); static void parse_logdir(const char *); static void parse_maxupdateskew(const char *); +static void parse_maxclockerror(const char *); static void parse_peer(const char *); static void parse_acquisitionport(const char *); static void parse_port(const char *); @@ -120,6 +121,7 @@ static char *drift_file = NULL; static char *rtc_file = NULL; static unsigned long command_key_id; static double max_update_skew = 1000.0; +static double max_clock_error = 10; /* in ppm */ static int cmd_port = -1; @@ -232,6 +234,7 @@ static const Command commands[] = { {"dumponexit", 10, parse_dumponexit}, {"dumpdir", 7, parse_dumpdir}, {"maxupdateskew", 13, parse_maxupdateskew}, + {"maxclockerror", 13, parse_maxclockerror}, {"commandkey", 10, parse_commandkey}, {"initstepslew", 12, parse_initstepslew}, {"local", 5, parse_local}, @@ -593,6 +596,16 @@ parse_maxupdateskew(const char *line) /* ================================================== */ +static void +parse_maxclockerror(const char *line) +{ + if (sscanf(line, "%lf", &max_clock_error) != 1) { + LOG(LOGS_WARN, LOGF_Configure, "Could not read max clock error at line %d in file", line_number); + } +} + +/* ================================================== */ + static void parse_driftfile(const char *line) { @@ -1407,6 +1420,14 @@ CNF_GetMaxUpdateSkew(void) /* ================================================== */ +double +CNF_GetMaxClockError(void) +{ + return max_clock_error; +} + +/* ================================================== */ + int CNF_GetManualEnabled(void) { diff --git a/conf.h b/conf.h index 9ccef77..e2aac48 100644 --- a/conf.h +++ b/conf.h @@ -77,6 +77,7 @@ extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale); /* Value returned in ppm, as read from file */ extern double CNF_GetMaxUpdateSkew(void); +extern double CNF_GetMaxClockError(void); extern int CNF_AllowLocalReference(int *stratum); extern void CNF_SetupAccessRestrictions(void); diff --git a/local.c b/local.c index 64d635b..da95673 100644 --- a/local.c +++ b/local.c @@ -34,6 +34,7 @@ #include #include +#include "conf.h" #include "local.h" #include "localp.h" #include "memory.h" @@ -91,6 +92,8 @@ static DispersionNotifyListEntry dispersion_notify_list; static int precision_log; static double precision_quantum; +static double max_clock_error; + /* ================================================== */ /* Define the number of increments of the system clock that we want @@ -157,6 +160,8 @@ LCL_Initialise(void) temp_comp_ppm = 0.0; calculate_sys_precision(); + + max_clock_error = CNF_GetMaxClockError() * 1e-6; } /* ================================================== */ @@ -187,6 +192,14 @@ LCL_GetSysPrecisionAsQuantum(void) /* ================================================== */ +double +LCL_GetMaxClockError(void) +{ + return max_clock_error; +} + +/* ================================================== */ + void LCL_AddParameterChangeHandler(LCL_ParameterChangeHandler handler, void *anything) { diff --git a/local.h b/local.h index ce29918..06eb697 100644 --- a/local.h +++ b/local.h @@ -165,6 +165,10 @@ extern int LCL_GetSysPrecisionAsLog(void); /* Routine to read the system precision in terms of the actual time step */ extern double LCL_GetSysPrecisionAsQuantum(void); +/* Routine to read the maximum frequency error of the local clock. This + is a frequency stability, not an absolute error. */ +extern double LCL_GetMaxClockError(void); + /* Routine to initialise the module (to be called once at program start-up) */ diff --git a/reference.c b/reference.c index 01b53ef..c4b6013 100644 --- a/reference.c +++ b/reference.c @@ -757,7 +757,7 @@ REF_GetReferenceParams *stratum = our_stratum; UTI_DiffTimevalsToDouble(&elapsed, local_time, &our_ref_time); - extra_dispersion = (our_skew + fabs(our_residual_freq)) * elapsed; + extra_dispersion = (our_skew + fabs(our_residual_freq) + LCL_GetMaxClockError()) * elapsed; *leap_status = our_leap_status; *ref_id = our_ref_id; @@ -870,7 +870,7 @@ REF_GetTrackingReport(RPT_TrackingReport *rep) if (are_we_synchronised) { UTI_DiffTimevalsToDouble(&elapsed, &now_cooked, &our_ref_time); - extra_dispersion = (our_skew + fabs(our_residual_freq)) * elapsed; + extra_dispersion = (our_skew + fabs(our_residual_freq) + LCL_GetMaxClockError()) * elapsed; rep->ref_id = our_ref_id; rep->ip_addr = our_ref_ip;