refclock: stop requiring 4 samples in median filter
Reduce the minimum number of samples required by the filter from min(4, length) to 1. This makes the filtering less confusing. The sample lifetime is limited to one poll and the default filtering of the SOCK refclock (where the maximum number of samples per poll is unknown) is identical to the other refclocks. A concern with potential variability in number of samples per poll below 4 is switching between different calculations of dispersion in combine_selected_samples() in samplefilt.c. The 106-refclock test shows how the order of refclocks in the config can impact the first filtered sample and selection. If the PPS refclock follows SHM, a single low-quality PPS sample is accepted in the same poll where SHM is selected and the initial clock correction started, which causes larger skew later and delays the first selection of the PPS refclock.
This commit is contained in:
parent
b9b338a8df
commit
12237bf283
3 changed files with 39 additions and 20 deletions
|
@ -661,14 +661,13 @@ value is the estimated precision of the system clock.
|
||||||
Maximum allowed dispersion for filtered samples (in seconds). Samples with
|
Maximum allowed dispersion for filtered samples (in seconds). Samples with
|
||||||
larger estimated dispersion are ignored. By default, this limit is disabled.
|
larger estimated dispersion are ignored. By default, this limit is disabled.
|
||||||
*filter* _samples_:::
|
*filter* _samples_:::
|
||||||
This option sets the length of the median filter which is used to reduce the
|
This option sets the maximum number of samples that can be stored in the median
|
||||||
noise in the measurements. With each poll about 40 percent of the stored
|
filter between polls of the source. The filter combines about 60 percent of the
|
||||||
samples are discarded and one final sample is calculated as an average of the
|
samples closest to the median offset into one sample. If more samples are
|
||||||
remaining samples. If the length is 4 or more, at least 4 samples have to be
|
received by the driver between polls, the oldest samples will be dropped. One
|
||||||
collected between polls. For lengths below 4, the filter has to be full. The
|
sample per poll is sufficient for the source to be selectable. The default
|
||||||
default is 64. With drivers that perform their own polling (PPS, PHC, SHM), the
|
is 64. Note that the PHC driver has additional filtering based on the reading
|
||||||
maximum value is adjusted to the number of driver polls per source poll, i.e.
|
delay.
|
||||||
2^(_poll_ - _dpoll_).
|
|
||||||
*prefer*:::
|
*prefer*:::
|
||||||
Prefer this source over other selectable sources without the *prefer* option.
|
Prefer this source over other selectable sources without the *prefer* option.
|
||||||
*noselect*:::
|
*noselect*:::
|
||||||
|
|
14
refclock.c
14
refclock.c
|
@ -233,12 +233,10 @@ RCL_AddRefclock(RefclockParameters *params)
|
||||||
if (inst->driver_poll > inst->poll)
|
if (inst->driver_poll > inst->poll)
|
||||||
inst->driver_poll = inst->poll;
|
inst->driver_poll = inst->poll;
|
||||||
|
|
||||||
|
/* Adjust the filter length to save memory if the expected number
|
||||||
|
of samples is smaller */
|
||||||
max_samples = 1 << (inst->poll - inst->driver_poll);
|
max_samples = 1 << (inst->poll - inst->driver_poll);
|
||||||
if (max_samples < params->filter_length) {
|
if (max_samples < params->filter_length) {
|
||||||
if (max_samples < 4) {
|
|
||||||
LOG(LOGS_WARN, "Setting filter length for %s to %d",
|
|
||||||
UTI_RefidToString(inst->ref_id), max_samples);
|
|
||||||
}
|
|
||||||
params->filter_length = max_samples;
|
params->filter_length = max_samples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,11 +244,9 @@ RCL_AddRefclock(RefclockParameters *params)
|
||||||
if (inst->driver->init && !inst->driver->init(inst))
|
if (inst->driver->init && !inst->driver->init(inst))
|
||||||
LOG_FATAL("refclock %s initialisation failed", params->driver_name);
|
LOG_FATAL("refclock %s initialisation failed", params->driver_name);
|
||||||
|
|
||||||
/* Require the filter to have at least 4 samples to produce a filtered
|
/* Don't require more than one sample per poll and combine 60% of the
|
||||||
sample, or be full for shorter lengths, and combine 60% of samples
|
samples closest to the median offset */
|
||||||
closest to the median */
|
inst->filter = SPF_CreateInstance(1, params->filter_length, params->max_dispersion, 0.6);
|
||||||
inst->filter = SPF_CreateInstance(MIN(params->filter_length, 4), params->filter_length,
|
|
||||||
params->max_dispersion, 0.6);
|
|
||||||
|
|
||||||
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, 0, params->sel_options,
|
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, 0, params->sel_options,
|
||||||
NULL, params->min_samples, params->max_samples,
|
NULL, params->min_samples, params->max_samples,
|
||||||
|
|
|
@ -89,9 +89,9 @@ Root delay : 0\.000000001 seconds
|
||||||
check_file_messages "20.* PPS1.*- N " 60 63 refclocks.log || test_fail
|
check_file_messages "20.* PPS1.*- N " 60 63 refclocks.log || test_fail
|
||||||
rm -f tmp/refclocks.log
|
rm -f tmp/refclocks.log
|
||||||
|
|
||||||
min_sync_time=80
|
min_sync_time=180
|
||||||
max_sync_time=180
|
max_sync_time=260
|
||||||
chronyc_start=220
|
chronyc_start=270
|
||||||
client_conf="
|
client_conf="
|
||||||
refclock SHM 0 refid NMEA offset 0.35 delay 0.1
|
refclock SHM 0 refid NMEA offset 0.35 delay 0.1
|
||||||
refclock PPS /dev/pps0
|
refclock PPS /dev/pps0
|
||||||
|
@ -112,6 +112,30 @@ Root delay : 0\.000000001 seconds
|
||||||
check_file_messages "20.* PPS1.*[0-9] N " 800 960 refclocks.log || test_fail
|
check_file_messages "20.* PPS1.*[0-9] N " 800 960 refclocks.log || test_fail
|
||||||
check_file_messages "20.* PPS1.*- N " 50 63 refclocks.log || test_fail
|
check_file_messages "20.* PPS1.*- N " 50 63 refclocks.log || test_fail
|
||||||
rm -f tmp/refclocks.log
|
rm -f tmp/refclocks.log
|
||||||
|
|
||||||
|
min_sync_time=80
|
||||||
|
max_sync_time=180
|
||||||
|
chronyc_start=220
|
||||||
|
# Swapped order of SHM and PPS impacts first accepted sample
|
||||||
|
client_conf="
|
||||||
|
refclock PPS /dev/pps0
|
||||||
|
refclock SHM 0 refid NMEA offset 0.35 delay 0.1
|
||||||
|
logdir tmp
|
||||||
|
log refclocks
|
||||||
|
maxupdateskew 10000"
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_source_selection || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
check_chronyc_output "^Reference ID.*50505330 \(PPS0\)
|
||||||
|
Stratum.*: 1
|
||||||
|
.*
|
||||||
|
Root delay : 0\.000000001 seconds
|
||||||
|
.*$" || test_fail
|
||||||
|
|
||||||
|
check_file_messages "20.* PPS0.*[0-9] N " 800 960 refclocks.log || test_fail
|
||||||
|
check_file_messages "20.* PPS0.*- N " 50 63 refclocks.log || test_fail
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export CLKNETSIM_PHC_JITTER_OFF=$[2 * 25 * 492]
|
export CLKNETSIM_PHC_JITTER_OFF=$[2 * 25 * 492]
|
||||||
|
|
Loading…
Reference in a new issue