sourcestats: add fixed asymmetry

Rework the code to allow the jitter asymmetry to be specified.
This commit is contained in:
Miroslav Lichvar 2017-08-22 16:26:40 +02:00
parent d0964ffa83
commit b06d74ab73
7 changed files with 59 additions and 32 deletions

View file

@ -586,7 +586,7 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
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); 0.0, 1.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, 0.0); params->min_samples, params->max_samples, 0.0, 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,8 +213,9 @@ 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, SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, int sel_options,
int min_samples, int max_samples, double min_delay) IPAddr *addr, int min_samples, int max_samples,
double min_delay, double asymmetry)
{ {
SRC_Instance result; SRC_Instance result;
@ -226,7 +227,8 @@ 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, min_delay); result->stats = SST_CreateInstance(ref_id, addr, min_samples, max_samples,
min_delay, asymmetry);
if (n_sources == max_n_sources) { if (n_sources == max_n_sources) {
/* Reallocate memory */ /* Reallocate memory */

View file

@ -59,8 +59,9 @@ 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, extern SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, int sel_options,
int min_samples, int max_samples, double min_delay); IPAddr *addr, int min_samples, int max_samples,
double min_delay, double asymmetry);
/* 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

@ -85,6 +85,9 @@ struct SST_Stats_Record {
/* User defined minimum delay */ /* User defined minimum delay */
double fixed_min_delay; double fixed_min_delay;
/* User defined asymmetry of network jitter */
double fixed_asymmetry;
/* 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;
@ -200,7 +203,8 @@ 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, double min_delay) SST_CreateInstance(uint32_t refid, IPAddr *addr, int min_samples, int max_samples,
double min_delay, double asymmetry)
{ {
SST_Stats inst; SST_Stats inst;
inst = MallocNew(struct SST_Stats_Record); inst = MallocNew(struct SST_Stats_Record);
@ -208,6 +212,7 @@ SST_CreateInstance(uint32_t refid, IPAddr *addr, int min_samples, int max_sample
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; inst->fixed_min_delay = min_delay;
inst->fixed_asymmetry = asymmetry;
SST_SetRefid(inst, refid, addr); SST_SetRefid(inst, refid, addr);
SST_ResetInstance(inst); SST_ResetInstance(inst);
@ -422,14 +427,43 @@ find_min_delay_sample(SST_Stats inst)
minimum network delay. This can significantly improve the accuracy and minimum network delay. This can significantly improve the accuracy and
stability of the estimated offset and frequency. */ stability of the estimated offset and frequency. */
static int
estimate_asymmetry(double *times_back, double *offsets, double *delays, int n,
double *asymmetry, int *asymmetry_run)
{
double a;
/* Reset the counter when the regression fails or the sign changes */
if (!RGR_MultipleRegress(times_back, delays, offsets, n, &a) ||
a * *asymmetry_run < 0.0) {
*asymmetry = 0;
*asymmetry_run = 0.0;
return 0;
}
if (a <= -MIN_ASYMMETRY && *asymmetry_run > -MAX_ASYMMETRY_RUN)
(*asymmetry_run)--;
else if (a >= MIN_ASYMMETRY && *asymmetry_run < MAX_ASYMMETRY_RUN)
(*asymmetry_run)++;
if (abs(*asymmetry_run) < MIN_ASYMMETRY_RUN)
return 0;
*asymmetry = CLAMP(-MAX_ASYMMETRY, a, MAX_ASYMMETRY);
return 1;
}
/* ================================================== */
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, min_delay, delays[MAX_SAMPLES * REGRESS_RUNS_RATIO]; double min_delay, delays[MAX_SAMPLES * REGRESS_RUNS_RATIO];
int i, n; int i, n;
/* Don't try to estimate the asymmetry with reference clocks */ /* Check if the asymmetry was not specified to be zero */
if (!inst->ip_addr) if (inst->fixed_asymmetry == 0.0)
return; return;
min_delay = SST_MinRoundTripDelay(inst); min_delay = SST_MinRoundTripDelay(inst);
@ -439,29 +473,17 @@ correct_asymmetry(SST_Stats inst, double *times_back, double *offsets)
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)] -
min_delay; min_delay;
/* Reset the counter when the regression fails or the sign changes */ if (fabs(inst->fixed_asymmetry) <= MAX_ASYMMETRY) {
if (!RGR_MultipleRegress(times_back, delays, offsets, n, &asymmetry) || inst->asymmetry = inst->fixed_asymmetry;
asymmetry * inst->asymmetry_run < 0.0) { } else {
inst->asymmetry_run = 0; if (!estimate_asymmetry(times_back, offsets, delays, n,
inst->asymmetry = 0.0; &inst->asymmetry, &inst->asymmetry_run))
return; return;
} }
asymmetry = CLAMP(-MAX_ASYMMETRY, asymmetry, MAX_ASYMMETRY);
if (asymmetry <= -MIN_ASYMMETRY && inst->asymmetry_run > -MAX_ASYMMETRY_RUN)
inst->asymmetry_run--;
else if (asymmetry >= MIN_ASYMMETRY && inst->asymmetry_run < MAX_ASYMMETRY_RUN)
inst->asymmetry_run++;
if (abs(inst->asymmetry_run) < MIN_ASYMMETRY_RUN)
return;
/* Correct the offsets */ /* Correct the offsets */
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
offsets[i] -= asymmetry * delays[i]; offsets[i] -= inst->asymmetry * delays[i];
inst->asymmetry = asymmetry;
} }
/* ================================================== */ /* ================================================== */

View file

@ -39,7 +39,8 @@ 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, extern SST_Stats SST_CreateInstance(uint32_t refid, IPAddr *addr,
int min_samples, int max_samples, double min_delay); int min_samples, int max_samples,
double min_delay, double asymmetry);
/* 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,8 @@ 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, 0.0); SRC_DEFAULT_MINSAMPLES, SRC_DEFAULT_MAXSAMPLES,
0.0, 1.0);
SRC_UpdateReachability(srcs[j], 1); SRC_UpdateReachability(srcs[j], 1);
samples = (i + j) % 5 + 3; samples = (i + j) % 5 + 3;