Re: [chrony-dev] PPS reference clock rejected because of high dispersion |
[ Thread Index |
Date Index
| More chrony.tuxfamily.org/chrony-dev Archives
]
On Tue, May 20, 2014 at 01:51:59PM +0200, Miroslav Lichvar wrote:
> > I'm not sure exactly where you want to do this check. The dispersion
> > calculated at the beginning of RCL_AddSample and RCL_AddPulse is
> > actually based on the average dispersion from the filter. I don't see
> > how rejecting samples when the filter result is too big will help making
> > the average dispersion lower, as you will get in the same deadlock
> > situation again. Rejected samples do not update the filter, so the
> > average dispersion will never get lower anymore.
>
> If you do it in filter_get_sample() before the variance stat is
> updated, it should never be larger and it shouldn't stuck.
Here is a patch doing that. Does it fix the problem for you?
--
Miroslav Lichvar
diff --git a/conf.c b/conf.c
index 5e419d4..11c4136 100644
--- a/conf.c
+++ b/conf.c
@@ -600,7 +600,7 @@ parse_refclock(char *line)
{
int i, n, poll, dpoll, filter_length, pps_rate;
uint32_t ref_id, lock_ref_id;
- double offset, delay, precision;
+ double offset, delay, precision, max_dispersion;
char *p, *cmd, *name, *param;
unsigned char ref[5];
SRC_SelectOption sel_option;
@@ -616,6 +616,7 @@ parse_refclock(char *line)
offset = 0.0;
delay = 1e-9;
precision = 0.0;
+ max_dispersion = 0.0;
ref_id = 0;
lock_ref_id = 0;
sel_option = SRC_SelectNormal;
@@ -674,6 +675,9 @@ parse_refclock(char *line)
} else if (!strcasecmp(cmd, "precision")) {
if (sscanf(line, "%lf%n", &precision, &n) != 1)
break;
+ } else if (!strcasecmp(cmd, "maxdispersion")) {
+ if (sscanf(line, "%lf%n", &max_dispersion, &n) != 1)
+ break;
} else if (!strcasecmp(cmd, "noselect")) {
n = 0;
sel_option = SRC_SelectNoselect;
@@ -700,6 +704,7 @@ parse_refclock(char *line)
refclock_sources[i].offset = offset;
refclock_sources[i].delay = delay;
refclock_sources[i].precision = precision;
+ refclock_sources[i].max_dispersion = max_dispersion;
refclock_sources[i].sel_option = sel_option;
refclock_sources[i].ref_id = ref_id;
refclock_sources[i].lock_ref_id = lock_ref_id;
diff --git a/refclock.c b/refclock.c
index c9618aa..885a4d2 100644
--- a/refclock.c
+++ b/refclock.c
@@ -57,6 +57,7 @@ struct MedianFilter {
int last;
int avg_var_n;
double avg_var;
+ double max_var;
struct FilterSample *samples;
int *selected;
double *x_data;
@@ -100,7 +101,7 @@ static void slew_samples(struct timeval *raw, struct timeval *cooked, double dfr
static void add_dispersion(double dispersion, void *anything);
static void log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion);
-static void filter_init(struct MedianFilter *filter, int length);
+static void filter_init(struct MedianFilter *filter, int length, double max_dispersion);
static void filter_fini(struct MedianFilter *filter);
static void filter_reset(struct MedianFilter *filter);
static double filter_get_avg_sample_dispersion(struct MedianFilter *filter);
@@ -210,6 +211,8 @@ RCL_AddRefclock(RefclockParameters *params)
if (pps_source) {
if (inst->pps_rate < 1)
inst->pps_rate = 1;
+ if (params->max_dispersion == 0.0)
+ params->max_dispersion = 0.1;
} else {
inst->pps_rate = 0;
}
@@ -245,7 +248,7 @@ RCL_AddRefclock(RefclockParameters *params)
return 0;
}
- filter_init(&inst->filter, params->filter_length);
+ filter_init(&inst->filter, params->filter_length, params->max_dispersion);
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_option, NULL);
@@ -616,7 +619,7 @@ log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int
}
static void
-filter_init(struct MedianFilter *filter, int length)
+filter_init(struct MedianFilter *filter, int length, double max_dispersion)
{
if (length < 1)
length = 1;
@@ -628,6 +631,7 @@ filter_init(struct MedianFilter *filter, int length)
/* set first estimate to system precision */
filter->avg_var_n = 0;
filter->avg_var = LCL_GetSysPrecisionAsQuantum() * LCL_GetSysPrecisionAsQuantum();
+ filter->max_var = max_dispersion * max_dispersion;
filter->samples = MallocArray(struct FilterSample, filter->length);
filter->selected = MallocArray(int, filter->length);
filter->x_data = MallocArray(double, filter->length);
@@ -855,6 +859,9 @@ filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, doub
d = sqrt(var);
}
+ if (filter->max_var > 0.0 && var > filter->max_var)
+ return 0;
+
prev_avg_var = filter->avg_var;
/* update exponential moving average of the variance */
diff --git a/refclock.h b/refclock.h
index 5854139..b2122d3 100644
--- a/refclock.h
+++ b/refclock.h
@@ -43,6 +43,7 @@ typedef struct {
double offset;
double delay;
double precision;
+ double max_dispersion;
SRC_SelectOption sel_option;
} RefclockParameters;