* maxslewrate directive:: Set maximum slew rate
* maxupdateskew directive:: Stop bad estimates upsetting machine clock
* minsamples directive:: Set minimum number of samples per source
+* minsources directive:: Set minimum number of selectable sources to update clock
* noclientlog directive:: Prevent chronyd from gathering data about clients
* peer directive:: Specify an NTP peer
* pidfile directive:: Specify the file where chronyd's pid is written
minsamples <samples>
@end example
@c }}}
+@c {{{ minsources
+@node minsources directive
+@subsection minsources
+The @code{minsources} directive sets the minimum number of sources that need
+to be considered as selectable in the source selection algorithm before the
+local clock is updated. The default value is 1.
+
+Setting this option to a larger number can be used to improve the reliability.
+More sources will have to agree with each other and the clock will not be
+updated when only one source (which could be serving wrong time) is reachable.
+
+The syntax is
+
+@example
+minsources <sources>
+@end example
+@c }}}
@c {{{ noclientlog
@node noclientlog directive
@subsection noclientlog
/* Threshold for automatic RTC trimming */
static double rtc_autotrim_threshold = 0.0;
+/* Minimum number of selectables sources required to update the clock */
+static int min_sources = 1;
+
/* Number of updates before offset checking, number of ignored updates
before exiting and the maximum allowed offset */
static int max_offset_delay = -1;
parse_double(p, &max_update_skew);
} else if (!strcasecmp(command, "minsamples")) {
parse_int(p, &min_samples);
+ } else if (!strcasecmp(command, "minsources")) {
+ parse_int(p, &min_sources);
} else if (!strcasecmp(command, "noclientlog")) {
no_client_log = parse_null(p);
} else if (!strcasecmp(command, "peer")) {
/* ================================================== */
+int
+CNF_GetMinSources(void)
+{
+ return min_sources;
+}
+
+/* ================================================== */
+
char *
CNF_GetHwclockFile(void)
{
extern int CNF_GetMaxSamples(void);
extern int CNF_GetMinSamples(void);
+extern int CNF_GetMinSources(void);
+
extern double CNF_GetRtcAutotrim(void);
extern char *CNF_GetHwclockFile(void);
SRC_STALE, /* Has older samples than others */
SRC_FALSETICKER, /* Doesn't agree with others */
SRC_JITTERY, /* Scatter worse than other's dispersion (not used) */
+ SRC_WAITS_SOURCES, /* Not enough sources, selection postponed */
SRC_NONPREFERRED, /* Others have prefer option */
SRC_WAITS_UPDATE, /* No updates, selection postponed */
SRC_DISTANT, /* Others have shorter root distance */
n_sel_sources = j;
#endif
- if (n_sel_sources == 0) {
+ if (n_sel_sources == 0 || n_sel_sources < CNF_GetMinSources()) {
if (selected_source_index != INVALID_SOURCE) {
- log_selection_message("Can't synchronise: no selectable sources", NULL);
+ log_selection_message("Can't synchronise: %s selectable sources",
+ n_sel_sources ? "not enough" : "no");
selected_source_index = INVALID_SOURCE;
}
+ mark_ok_sources(SRC_WAITS_SOURCES);
return;
}
case SRC_JITTERY:
report->state = RPT_JITTERY;
break;
+ case SRC_WAITS_SOURCES:
case SRC_NONPREFERRED:
case SRC_WAITS_UPDATE:
case SRC_DISTANT: