]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
refclock: add maxdispersion option
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 21 May 2014 12:27:50 +0000 (14:27 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Fri, 23 May 2014 14:15:28 +0000 (16:15 +0200)
This can be used to prevent accumulation of samples with estimated
dispersion above given limit. By default, this limit is disabled.

chrony.texi.in
conf.c
refclock.c
refclock.h

index 6503ca89641c2008da9b657d80b577d0c4f89965..47c6079f595ff9c0ac02a3f3fb08baa548812525 100644 (file)
@@ -2599,6 +2599,10 @@ sources.  The default is 1e-9 (1 nanosecond).
 @item precision
 Refclock precision (in seconds).  The default is 1e-6 (1 microsecond)
 for SHM refclock, and 1e-9 (1 nanosecond) for SOCK, PPS and PHC refclocks.
+@item maxdispersion
+Maximum allowed dispersion for filtered samples (in seconds).  Samples
+with larger estimated dispersion are ignored.  By default, this limit
+is disabled.
 @item prefer
 Prefer this source over sources without prefer option.
 @item noselect
diff --git a/conf.c b/conf.c
index 50ed760ca573918dbae58c8c723fc25414cae437..03666eb2cbe6c0071767f3dc1af87ae29c0786ad 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -593,7 +593,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;
@@ -609,6 +609,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;
@@ -667,6 +668,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;
@@ -693,6 +697,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;
index dfd2b69c48a68f8c683c163dfea64c2616ccac00..0cd4754103fb92f0aad0f10b86b55746eefd8929 100644 (file)
@@ -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);
@@ -245,7 +246,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);
 
@@ -622,7 +623,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;
@@ -634,6 +635,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);
@@ -861,6 +863,13 @@ filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, doub
     d = sqrt(var);
   }
 
+  /* drop the sample if variance is larger than allowed maximum */
+  if (filter->max_var > 0.0 && var > filter->max_var) {
+    DEBUG_LOG(LOGF_Refclock, "filter dispersion too large disp=%.9f max=%.9f",
+        sqrt(var), sqrt(filter->max_var));
+    return 0;
+  }
+
   prev_avg_var = filter->avg_var;
 
   /* update exponential moving average of the variance */
index 5854139edc68cf84187be113ae6074c071e3d3f7..b2122d34c0df0ec5223fac92e3da95ab8009b844 100644 (file)
@@ -43,6 +43,7 @@ typedef struct {
   double offset;
   double delay;
   double precision;
+  double max_dispersion;
   SRC_SelectOption sel_option;
 } RefclockParameters;