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;
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/