diff --git a/chrony.texi.in b/chrony.texi.in index eee4b84..63de048 100644 --- a/chrony.texi.in +++ b/chrony.texi.in @@ -1155,6 +1155,7 @@ the configuration file is ignored. * maxchange directive:: Set maximum allowed offset * maxclockerror directive:: Set maximum frequency error of local clock * maxsamples directive:: Set maximum number of samples per source +* maxslewrate directive:: Set maximum slew rate * maxupdateskew directive:: Stop bad estimates upsetting machine clock * minsamples directive:: Set minimum number of samples per source * noclientlog directive:: Prevent chronyd from gathering data about clients @@ -1536,8 +1537,10 @@ The syntax is corrtimeratio 100 @end example -The current remaining correction is shown in the @code{tracking} report -(@pxref{tracking command}) as the @code{System time} value. +The maximum allowed slew rate can be set by the @code{maxslewrate} +directive (@pxref{maxslewrate directive}. The current remaining +correction is shown in the @code{tracking} report (@pxref{tracking +command}) as the @code{System time} value. @c }}} @c {{{ deny @node deny directive @@ -2398,6 +2401,23 @@ The syntax is maxsamples @end example @c }}} +@c {{{ maxslewrate +@node maxslewrate directive +@subsection maxslewrate +The @code{maxslewrate} directive sets the maximum rate at which @code{chronyd} +is allowed to slew the time. It limits the slew rate controlled by the +correction time ratio (@pxref{corrtimeratio directive}) and is effective +only on systems where @code{chronyd} is able to control the rate (so +far only Linux). + +By default, the maximum slew rate is 83333.333 ppm (one twelfth). + +The syntax is + +@example +maxslewrate +@end example +@c }}} @c {{{ maxupdateskew @node maxupdateskew directive @subsection maxupdateskew diff --git a/conf.c b/conf.c index 5e419d4..26fd605 100644 --- a/conf.c +++ b/conf.c @@ -88,6 +88,7 @@ static unsigned long command_key_id; 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_slew_rate = 1e6 / 12.0; /* in ppm */ static double reselect_distance = 1e-4; static double stratum_weight = 1.0; @@ -422,6 +423,8 @@ CNF_ParseLine(const char *filename, int number, char *line) parse_double(p, &max_clock_error); } else if (!strcasecmp(command, "maxsamples")) { parse_int(p, &max_samples); + } else if (!strcasecmp(command, "maxslewrate")) { + parse_double(p, &max_slew_rate); } else if (!strcasecmp(command, "maxupdateskew")) { parse_double(p, &max_update_skew); } else if (!strcasecmp(command, "minsamples")) { @@ -1390,6 +1393,14 @@ CNF_GetCorrectionTimeRatio(void) /* ================================================== */ +double +CNF_GetMaxSlewRate(void) +{ + return max_slew_rate; +} + +/* ================================================== */ + double CNF_GetReselectDistance(void) { diff --git a/conf.h b/conf.h index 2ee9a00..7b98bcf 100644 --- a/conf.h +++ b/conf.h @@ -81,6 +81,7 @@ extern void CNF_GetLinuxFreqScale(int *set, double *freq_scale); extern double CNF_GetMaxUpdateSkew(void); extern double CNF_GetMaxClockError(void); extern double CNF_GetCorrectionTimeRatio(void); +extern double CNF_GetMaxSlewRate(void); extern double CNF_GetReselectDistance(void); extern double CNF_GetStratumWeight(void); diff --git a/sys_generic.c b/sys_generic.c index d6c109d..62a5a7c 100644 --- a/sys_generic.c +++ b/sys_generic.c @@ -30,6 +30,7 @@ #include "sys_generic.h" +#include "conf.h" #include "local.h" #include "localp.h" #include "logging.h" @@ -52,6 +53,9 @@ static double max_freq; in local time */ static double max_freq_change_delay; +/* Maximum allowed frequency offset relative to the base frequency */ +static double max_corr_freq; + /* Amount of outstanding offset to process */ static double offset_register; @@ -62,9 +66,6 @@ static double offset_register; as set by drv_set_freq (not in ppm) */ static double slew_freq; -/* Maximum allowed slewing frequency */ -#define MAX_SLEW_FREQ (1 / 12.0) - /* Time (raw) of last update of slewing frequency and offset */ static struct timeval slew_start; @@ -129,10 +130,10 @@ update_slew(void) /* Get frequency offset needed to slew the offset in the duration and clamp it to the allowed maximum */ corr_freq = offset_register / duration; - if (corr_freq < -MAX_SLEW_FREQ) - corr_freq = -MAX_SLEW_FREQ; - else if (corr_freq > MAX_SLEW_FREQ) - corr_freq = MAX_SLEW_FREQ; + if (corr_freq < -max_corr_freq) + corr_freq = -max_corr_freq; + else if (corr_freq > max_corr_freq) + corr_freq = max_corr_freq; /* Get the new real frequency and clamp it */ total_freq = base_freq + corr_freq * (1.0e6 - base_freq); @@ -275,6 +276,8 @@ SYS_Generic_CompleteFreqDriver(double max_set_freq_ppm, double max_set_freq_dela slew_freq = 0.0; offset_register = 0.0; + max_corr_freq = CNF_GetMaxSlewRate() / 1.0e6; + lcl_RegisterSystemDrivers(read_frequency, set_frequency, accrue_offset, sys_apply_step_offset ? sys_apply_step_offset : apply_step_offset,