parse_refclock(char *line)
{
int n, poll, dpoll, filter_length, pps_rate, min_samples_, max_samples_, sel_options;
- int local, max_lock_age, max_unreach, pps_forced, sel_option, stratum, tai;
+ int local, max_lock_age, max_unreach, pps_forced, sel_option, stratum, tai, optional;
uint32_t ref_id, lock_ref_id;
double offset, delay, precision, max_dispersion, pulse_width;
char *p, *cmd, *name, *param;
RefclockParameters *refclock;
+ optional = 0;
poll = 4;
dpoll = 0;
filter_length = 64;
} else if (!strcasecmp(cmd, "offset")) {
if (sscanf(line, "%lf%n", &offset, &n) != 1)
break;
+ } else if (!strcasecmp(cmd, "optional")) {
+ n = 0;
+ optional = 1;
} else if (!strcasecmp(cmd, "delay")) {
if (sscanf(line, "%lf%n", &delay, &n) != 1)
break;
refclock->driver_parameter = param;
refclock->driver_poll = dpoll;
refclock->poll = poll;
+ refclock->optional = optional;
refclock->filter_length = filter_length;
refclock->local = local;
refclock->pps_forced = pps_forced;
received in the last 8 polls). Only sources with at least one sample more
recent than the oldest sample of all reachable sources can be selected.
The default is 100000.
+*optional*:::
+This option indicates that the refclock device might be missing and *chronyd*
+is allowed to start even if the driver fails to initialise, causing the source
+to be ignored as if it was not specified in the configuration file.
[[manual]]*manual*::
The *manual* directive enables support at run-time for the
RCL_Instance inst;
inst = MallocNew(struct RCL_Instance_Record);
- *(RCL_Instance *)ARR_GetNewElement(refclocks) = inst;
if (strcmp(params->driver_name, "SHM") == 0) {
inst->driver = &RCL_SHM_driver;
inst->ref_id = params->ref_id;
else {
unsigned char ref[5] = { 0, 0, 0, 0, 0 };
- unsigned int index = ARR_GetSize(refclocks) - 1;
+ unsigned int index = ARR_GetSize(refclocks);
snprintf((char *)ref, sizeof (ref), "%3.3s", params->driver_name);
ref[3] = index % 10 + '0';
inst->driver_poll = inst->poll;
}
- if (inst->driver->init && !inst->driver->init(inst))
- LOG_FATAL("refclock %s initialisation failed", params->driver_name);
+ if (inst->driver->init && !inst->driver->init(inst)) {
+ LOG(params->optional ? LOGS_ERR : LOGS_FATAL, "Could not initialise refclock %s %s",
+ params->driver_name, params->driver_parameter);
+ Free(inst->driver_parameter);
+ Free(inst);
+ return 0;
+ }
/* Don't require more than one sample per poll and combine 60% of the
samples closest to the median offset */
params->driver_name, UTI_RefidToString(inst->ref_id),
inst->poll, inst->driver_poll, params->filter_length);
+ *(RCL_Instance *)ARR_GetNewElement(refclocks) = inst;
+
return 1;
}
char *driver_parameter;
int driver_poll;
int poll;
+ int optional;
int filter_length;
int local;
int pps_forced;
check_file_messages "20.* PHC0 " 0 0 tracking.log || test_fail
rm -f tmp/refclocks.log tmp/tracking.log
+reset_test_options
+
+cmdmon_unix=0
+client_conf="
+refclock PHC tmp/nosuch/ptp0 optional
+refclock SOCK tmp/nosuch/sock optional
+"
+num_refclocks=2
+if check_config_h 'FEAT_PPS 1'; then
+ client_conf+="refclock PPS tmp/nosuch/pps optional
+ "
+ num_refclocks=$[num_refclocks + 1]
+fi
+if check_config_h 'FEAT_RTC 1'; then
+ client_conf+="refclock RTC tmp/nosuch/rtc optional
+ "
+ num_refclocks=$[num_refclocks + 1]
+fi
+
+run_test || test_fail
+check_chronyd_exit || test_fail
+check_sync || test_fail
+check_log_messages "Could not initialise refclock \(PHC\|PPS\|RTC\|SOCK\)" \
+ $num_refclocks $num_refclocks || test_fail
+
test_pass