Rework the code to allow the jitter asymmetry to be specified.
SRC_NTP, params->sel_options,
&result->remote_addr.ip_addr,
params->min_samples, params->max_samples,
- 0.0);
+ 0.0, 1.0);
result->rx_timeout_id = 0;
result->tx_timeout_id = 0;
filter_init(&inst->filter, params->filter_length, params->max_dispersion);
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",
params->driver_name, UTI_RefidToString(inst->ref_id),
/* Function to create a new instance. This would be called by one of
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, double min_delay)
+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, double asymmetry)
{
SRC_Instance result;
max_samples = CNF_GetMaxSamples();
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) {
/* Reallocate memory */
/* Function to create a new instance. This would be called by one of
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, double min_delay);
+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, double asymmetry);
/* Function to get rid of a source when it is being unconfigured.
This may cause the current reference source to be reselected, if this
/* User defined minimum 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
buffer. */
int n_samples;
/* This function creates a new instance of the statistics handler */
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;
inst = MallocNew(struct SST_Stats_Record);
inst->min_samples = min_samples;
inst->max_samples = max_samples;
inst->fixed_min_delay = min_delay;
+ inst->fixed_asymmetry = asymmetry;
SST_SetRefid(inst, refid, addr);
SST_ResetInstance(inst);
minimum network delay. This can significantly improve the accuracy and
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
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;
- /* Don't try to estimate the asymmetry with reference clocks */
- if (!inst->ip_addr)
+ /* Check if the asymmetry was not specified to be zero */
+ if (inst->fixed_asymmetry == 0.0)
return;
min_delay = SST_MinRoundTripDelay(inst);
delays[i] = inst->peer_delays[get_runsbuf_index(inst, i - inst->runs_samples)] -
min_delay;
- /* Reset the counter when the regression fails or the sign changes */
- if (!RGR_MultipleRegress(times_back, delays, offsets, n, &asymmetry) ||
- asymmetry * inst->asymmetry_run < 0.0) {
- inst->asymmetry_run = 0;
- inst->asymmetry = 0.0;
- return;
+ if (fabs(inst->fixed_asymmetry) <= MAX_ASYMMETRY) {
+ inst->asymmetry = inst->fixed_asymmetry;
+ } else {
+ if (!estimate_asymmetry(times_back, offsets, delays, n,
+ &inst->asymmetry, &inst->asymmetry_run))
+ 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 */
for (i = 0; i < n; i++)
- offsets[i] -= asymmetry * delays[i];
-
- inst->asymmetry = asymmetry;
+ offsets[i] -= inst->asymmetry * delays[i];
}
/* ================================================== */
/* 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, double min_delay);
+ int min_samples, int max_samples,
+ double min_delay, double asymmetry);
/* This function deletes an instance of the statistics handler. */
extern void SST_DeleteInstance(SST_Stats inst);
DEBUG_LOG("added source %d options %d", j, sel_options);
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);
samples = (i + j) % 5 + 3;