* logchange directive:: Generate syslog messages if large offsets occur
* logdir directive:: Specify directory for logging
* 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.
* maxupdateskew directive:: Stop bad estimates upsetting machine clock
* noclientlog directive:: Prevent chronyd from gathering data about clients
This would send a mail message to root if a change of more than 0.5
seconds were applied to the system clock.
@c }}}
+@c {{{ makestep
+@node makestep directive
+@subsection makestep
+Normally chronyd will cause the system to gradually correct any time
+offset, by slowing down or speeding up the clock as required. In
+certain situations, the system clock may be so far adrift that this
+slewing process would take a very long time to correct the system clock.
+
+This directive forces @code{chronyd} to step system clock if the
+adjustment is larger than a threshold value, but only if there were no
+more clock updates since @code{chronyd} was started than a specified
+limit (a negative value can be used to disable the limit).
+
+This is particularly useful when using reference clocks, because the
+@code{initstepslew} directive (@pxref{initstepslew directive}) works
+only with NTP sources.
+
+An example of the use of this directive is
+
+@example
+makestep 1000 10
+@end example
+
+This would step system clock if the adjustment is larger than 1000
+seconds, but only in the first ten clock updates.
+@c }}}
@c {{{ manual
@node manual directive
@subsection manual
BE WARNED - certain software will be seriously affected by such jumps to
the system time. (That is the reason why chronyd uses slewing
normally.)
+
+The @code{makestep} directive in the configuration file can be used
+to step the clock automatically when the adjustment is larger than a
+specified threshold, see @ref{makestep directive}.
@c }}}
@c {{{ manual
@node manual command
static void
handle_make_step(CMD_Request *rx_message, CMD_Reply *tx_message)
{
- int status;
- status = LCL_MakeStep();
- if (status) {
- tx_message->status = htons(STT_SUCCESS);
- } else {
- tx_message->status = htons(STT_NOTENABLED);
- }
+ LCL_MakeStep(0.0);
+ tx_message->status = htons(STT_SUCCESS);
return;
}
static void parse_rtconutc(const char *);
static void parse_noclientlog(const char *);
static void parse_clientloglimit(const char *);
+static void parse_makestep(const char *);
static void parse_logchange(const char *);
static void parse_mailonchange(const char *);
static void parse_bindaddress(const char *);
incl. daylight saving). */
static int rtc_on_utc = 0;
+/* Limit and threshold for clock stepping */
+static int make_step_limit = 0;
+static double make_step_threshold = 0.0;
+
/* Flag set if we should log to syslog when a time adjustment
exceeding the threshold is initiated */
static int do_log_change = 0;
{"rtconutc", 8, parse_rtconutc},
{"noclientlog", 11, parse_noclientlog},
{"clientloglimit", 14, parse_clientloglimit},
+ {"makestep", 8, parse_makestep},
{"logchange", 9, parse_logchange},
{"mailonchange", 12, parse_mailonchange},
{"bindaddress", 11, parse_bindaddress},
/* ================================================== */
+static void
+parse_makestep(const char *line)
+{
+ if (sscanf(line, "%lf %d", &make_step_threshold, &make_step_limit) != 2) {
+ make_step_limit = 0;
+ LOG(LOGS_WARN, LOGF_Configure,
+ "Could not read threshold or update limit for stepping clock at line %d\n",
+ line_number);
+ }
+}
+
+/* ================================================== */
+
static void
parse_logchange(const char *line)
{
/* ================================================== */
+void
+CNF_GetMakeStep(int *limit, double *threshold)
+{
+ *limit = make_step_limit;
+ *threshold = make_step_threshold;
+}
+
+/* ================================================== */
+
void
CNF_GetLogChange(int *enabled, double *threshold)
{
extern int CNF_GetManualEnabled(void);
extern int CNF_GetCommandPort(void);
extern int CNF_GetRTCOnUTC(void);
+extern void CNF_GetMakeStep(int *limit, double *threshold);
extern void CNF_GetLogChange(int *enabled, double *threshold);
extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
extern int CNF_GetNoClientLog(void);
/* ================================================== */
/* Look at the current difference between the system time and the NTP
- time, and make a step to cancel it. */
+ time, and make a step to cancel it if it's larger than the threshold. */
int
-LCL_MakeStep(void)
+LCL_MakeStep(double threshold)
{
struct timeval raw;
double correction;
LCL_ReadRawTime(&raw);
correction = LCL_GetOffsetCorrection(&raw);
+ if (fabs(correction) <= threshold)
+ return 0;
+
/* Cancel remaining slew and make the step */
LCL_AccumulateOffset(correction);
LCL_ApplyStepOffset(-correction);
/* Routine to convert the outstanding system clock error to a step and
apply it, e.g. if the system clock has ended up an hour wrong due
to a timezone problem. */
-extern int LCL_MakeStep(void);
+extern int LCL_MakeStep(double threshold);
/* Routine to schedule a leap second. Leap second will be inserted
at the end of the day if argument is positive, deleted if negative,
/* Flag indicating that we are initialised */
static int initialised = 0;
+/* Threshold and update limit for stepping clock */
+static int make_step_limit;
+static double make_step_threshold;
+
/* Flag and threshold for logging clock changes to syslog */
static int do_log_change;
static double log_change_threshold;
enable_local_stratum = CNF_AllowLocalReference(&local_stratum);
+ CNF_GetMakeStep(&make_step_limit, &make_step_threshold);
CNF_GetLogChange(&do_log_change, &log_change_threshold);
CNF_GetMailOnChange(&do_mail_change, &mail_change_threshold, &mail_change_user);
/* ================================================== */
+static void
+maybe_make_step()
+{
+ if (make_step_limit == 0) {
+ return;
+ } else if (make_step_limit > 0) {
+ make_step_limit--;
+ }
+ LCL_MakeStep(make_step_threshold);
+}
+
+/* ================================================== */
+
static void
update_leap_status(NTP_Leap leap)
{
our_residual_freq = frequency;
}
+ maybe_make_step();
+
abs_freq_ppm = LCL_ReadAbsoluteFrequency();
write_log(ref_time,
maybe_log_offset(offset);
LCL_AccumulateFrequencyAndOffset(frequency, offset);
+ maybe_make_step();
abs_freq_ppm = LCL_ReadAbsoluteFrequency();