sourcestats: add fixed minimum delay

If the minimum delay is known (in a static network configuration), it
can replace the measured minimum from the register. This should improve
the stability of corrections for asymmetric jitter, sample weighting and
maxdelay* tests.
This commit is contained in:
Miroslav Lichvar 2017-08-17 16:44:18 +02:00
parent 3d08815efb
commit d0964ffa83
7 changed files with 26 additions and 10 deletions

View file

@ -585,7 +585,8 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr),
SRC_NTP, params->sel_options, SRC_NTP, params->sel_options,
&result->remote_addr.ip_addr, &result->remote_addr.ip_addr,
params->min_samples, params->max_samples); params->min_samples, params->max_samples,
0.0);
result->rx_timeout_id = 0; result->rx_timeout_id = 0;
result->tx_timeout_id = 0; result->tx_timeout_id = 0;

View file

@ -260,7 +260,7 @@ RCL_AddRefclock(RefclockParameters *params)
filter_init(&inst->filter, params->filter_length, params->max_dispersion); filter_init(&inst->filter, params->filter_length, params->max_dispersion);
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_options, NULL, inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_options, NULL,
params->min_samples, params->max_samples); params->min_samples, params->max_samples, 0.0);
DEBUG_LOG("refclock %s refid=%s poll=%d dpoll=%d filter=%d", DEBUG_LOG("refclock %s refid=%s poll=%d dpoll=%d filter=%d",
params->driver_name, UTI_RefidToString(inst->ref_id), params->driver_name, UTI_RefidToString(inst->ref_id),

View file

@ -213,7 +213,8 @@ void SRC_Finalise(void)
/* Function to create a new instance. This would be called by one of /* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */ the individual source-type instance creation routines. */
SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, int sel_options, IPAddr *addr, int min_samples, int max_samples) SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, int sel_options, IPAddr *addr,
int min_samples, int max_samples, double min_delay)
{ {
SRC_Instance result; SRC_Instance result;
@ -225,7 +226,7 @@ SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, int sel_optio
max_samples = CNF_GetMaxSamples(); max_samples = CNF_GetMaxSamples();
result = MallocNew(struct SRC_Instance_Record); result = MallocNew(struct SRC_Instance_Record);
result->stats = SST_CreateInstance(ref_id, addr, min_samples, max_samples); result->stats = SST_CreateInstance(ref_id, addr, min_samples, max_samples, min_delay);
if (n_sources == max_n_sources) { if (n_sources == max_n_sources) {
/* Reallocate memory */ /* Reallocate memory */

View file

@ -59,7 +59,8 @@ typedef enum {
/* Function to create a new instance. This would be called by one of /* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */ the individual source-type instance creation routines. */
extern SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, int sel_options, IPAddr *addr, int min_samples, int max_samples); extern SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, int sel_options, IPAddr *addr,
int min_samples, int max_samples, double min_delay);
/* Function to get rid of a source when it is being unconfigured. /* Function to get rid of a source when it is being unconfigured.
This may cause the current reference source to be reselected, if this This may cause the current reference source to be reselected, if this

View file

@ -82,6 +82,9 @@ struct SST_Stats_Record {
int min_samples; int min_samples;
int max_samples; int max_samples;
/* User defined minimum delay */
double fixed_min_delay;
/* Number of samples currently stored. The samples are stored in circular /* Number of samples currently stored. The samples are stored in circular
buffer. */ buffer. */
int n_samples; int n_samples;
@ -197,13 +200,14 @@ SST_Finalise(void)
/* This function creates a new instance of the statistics handler */ /* This function creates a new instance of the statistics handler */
SST_Stats SST_Stats
SST_CreateInstance(uint32_t refid, IPAddr *addr, int min_samples, int max_samples) SST_CreateInstance(uint32_t refid, IPAddr *addr, int min_samples, int max_samples, double min_delay)
{ {
SST_Stats inst; SST_Stats inst;
inst = MallocNew(struct SST_Stats_Record); inst = MallocNew(struct SST_Stats_Record);
inst->min_samples = min_samples; inst->min_samples = min_samples;
inst->max_samples = max_samples; inst->max_samples = max_samples;
inst->fixed_min_delay = min_delay;
SST_SetRefid(inst, refid, addr); SST_SetRefid(inst, refid, addr);
SST_ResetInstance(inst); SST_ResetInstance(inst);
@ -310,6 +314,9 @@ SST_AccumulateSample(SST_Stats inst, struct timespec *sample_time,
inst->root_dispersions[m] = root_dispersion; inst->root_dispersions[m] = root_dispersion;
inst->strata[m] = stratum; inst->strata[m] = stratum;
if (inst->peer_delays[n] < inst->fixed_min_delay)
inst->peer_delays[n] = 2.0 * inst->fixed_min_delay - inst->peer_delays[n];
if (!inst->n_samples || inst->peer_delays[n] < inst->peer_delays[inst->min_delay_sample]) if (!inst->n_samples || inst->peer_delays[n] < inst->peer_delays[inst->min_delay_sample])
inst->min_delay_sample = n; inst->min_delay_sample = n;
@ -418,18 +425,19 @@ find_min_delay_sample(SST_Stats inst)
static void static void
correct_asymmetry(SST_Stats inst, double *times_back, double *offsets) correct_asymmetry(SST_Stats inst, double *times_back, double *offsets)
{ {
double asymmetry, delays[MAX_SAMPLES * REGRESS_RUNS_RATIO]; double asymmetry, min_delay, delays[MAX_SAMPLES * REGRESS_RUNS_RATIO];
int i, n; int i, n;
/* Don't try to estimate the asymmetry with reference clocks */ /* Don't try to estimate the asymmetry with reference clocks */
if (!inst->ip_addr) if (!inst->ip_addr)
return; return;
min_delay = SST_MinRoundTripDelay(inst);
n = inst->runs_samples + inst->n_samples; n = inst->runs_samples + inst->n_samples;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
delays[i] = inst->peer_delays[get_runsbuf_index(inst, i - inst->runs_samples)] - delays[i] = inst->peer_delays[get_runsbuf_index(inst, i - inst->runs_samples)] -
inst->peer_delays[inst->min_delay_sample]; min_delay;
/* Reset the counter when the regression fails or the sign changes */ /* Reset the counter when the regression fails or the sign changes */
if (!RGR_MultipleRegress(times_back, delays, offsets, n, &asymmetry) || if (!RGR_MultipleRegress(times_back, delays, offsets, n, &asymmetry) ||
@ -771,8 +779,12 @@ SST_PredictOffset(SST_Stats inst, struct timespec *when)
double double
SST_MinRoundTripDelay(SST_Stats inst) SST_MinRoundTripDelay(SST_Stats inst)
{ {
if (inst->fixed_min_delay > 0.0)
return inst->fixed_min_delay;
if (!inst->n_samples) if (!inst->n_samples)
return DBL_MAX; return DBL_MAX;
return inst->peer_delays[inst->min_delay_sample]; return inst->peer_delays[inst->min_delay_sample];
} }

View file

@ -38,7 +38,8 @@ extern void SST_Initialise(void);
extern void SST_Finalise(void); extern void SST_Finalise(void);
/* This function creates a new instance of the statistics handler */ /* This function creates a new instance of the statistics handler */
extern SST_Stats SST_CreateInstance(uint32_t refid, IPAddr *addr, int min_samples, int max_samples); extern SST_Stats SST_CreateInstance(uint32_t refid, IPAddr *addr,
int min_samples, int max_samples, double min_delay);
/* This function deletes an instance of the statistics handler. */ /* This function deletes an instance of the statistics handler. */
extern void SST_DeleteInstance(SST_Stats inst); extern void SST_DeleteInstance(SST_Stats inst);

View file

@ -53,7 +53,7 @@ test_unit(void)
DEBUG_LOG("added source %d options %d", j, sel_options); DEBUG_LOG("added source %d options %d", j, sel_options);
srcs[j] = SRC_CreateNewInstance(UTI_IPToRefid(&addr), SRC_NTP, sel_options, &addr, srcs[j] = SRC_CreateNewInstance(UTI_IPToRefid(&addr), SRC_NTP, sel_options, &addr,
SRC_DEFAULT_MINSAMPLES, SRC_DEFAULT_MAXSAMPLES); SRC_DEFAULT_MINSAMPLES, SRC_DEFAULT_MAXSAMPLES, 0.0);
SRC_UpdateReachability(srcs[j], 1); SRC_UpdateReachability(srcs[j], 1);
samples = (i + j) % 5 + 3; samples = (i + j) % 5 + 3;