]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Track reachability in sources module
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 16 Dec 2010 15:01:29 +0000 (16:01 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Fri, 17 Dec 2010 12:22:29 +0000 (13:22 +0100)
Add new flag to source struct to indicate when source is selectable
(packets with good headers are received) and use a reachability
register for last 8 samples instead of the reachable flag. Source
drivers now provide only reachability updates.

ntp_core.c
refclock.c
sources.c
sources.h

index d87510ed0059ed56a3b6e37a118bb2f8bf36c0e2..40f77b4ab6ec0841ddd71809d77ae8a16e250ba3 100644 (file)
@@ -636,18 +636,6 @@ transmit_timeout(void *arg)
   inst->presend_done = 0; /* Reset for next time */
 
   ++inst->tx_count;
-  if (inst->tx_count >= 9) {
-    /* Mark source unreachable */
-    SRC_UnsetReachable(inst->source);
-  } else if (inst->tx_count >= 3) {
-    if (inst->auto_offline) {
-      NCR_TakeSourceOffline(inst);
-    }
-    /* Do reselection */
-    SRC_SelectSource(0);
-  } else {
-    /* Nothing */
-  }
 
   /* If the source loses connectivity, back off the sampling rate to reduce
      wasted sampling. If it's the source to which we are currently locked,
@@ -655,7 +643,14 @@ transmit_timeout(void *arg)
 
   if (inst->tx_count >= 2) {
     /* Implies we have missed at least one transmission */
+
     adjust_poll(inst, SRC_IsSyncPeer(inst->source) ? 0.1 : 0.25);
+
+    SRC_UpdateReachability(inst->source, 0);
+
+    if (inst->auto_offline && inst->tx_count >= 3) {
+      NCR_TakeSourceOffline(inst);
+    }
   }
 
   my_mode = inst->mode;
@@ -700,7 +695,7 @@ transmit_timeout(void *arg)
     case MD_OFFLINE:
       do_timer = 0;
       /* Mark source unreachable */
-      SRC_UnsetReachable(inst->source);
+      SRC_ResetReachability(inst->source);
       break;
     case MD_BURST_WAS_ONLINE:
     case MD_BURST_WAS_OFFLINE:
@@ -1074,16 +1069,17 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
 
   if (valid_header && valid_data) {
     inst->tx_count = 0;
+    SRC_UpdateReachability(inst->source, 1);
 
     /* Mark the source as suitable for synchronisation when both header and
        data are good, unmark when header is not good (i.e. the stratum is
        higher than ours) */
     if (good_header) {
       if (good_data) {
-        SRC_SetReachable(inst->source);
+        SRC_SetSelectable(inst->source);
       }
     } else {
-      SRC_UnsetReachable(inst->source);
+      SRC_UnsetSelectable(inst->source);
     }
   }
 
@@ -1202,7 +1198,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
     case MD_OFFLINE:
       requeue_transmit = 0;
       /* Mark source unreachable */
-      SRC_UnsetReachable(inst->source);
+      SRC_ResetReachability(inst->source);
       break; /* Even if we've received something, we don't want to
                 transmit back.  This might be a symmetric active peer
                 that is trying to talk to us. */
@@ -1714,7 +1710,7 @@ NCR_TakeSourceOffline(NCR_Instance inst)
         inst->timer_running = 0;
         inst->opmode = MD_OFFLINE;
         /* Mark source unreachable */
-        SRC_UnsetReachable(inst->source);
+        SRC_ResetReachability(inst->source);
       }
       break;
     case MD_OFFLINE:
index 4cfc343312c218ddda735dffd1c076449213017f..1922ebbb41b6477bfd1b445ccc3896979cda1717 100644 (file)
@@ -69,7 +69,6 @@ struct RCL_Instance_Record {
   int driver_poll;
   int driver_polled;
   int poll;
-  int missed_samples;
   int leap_status;
   int pps_rate;
   struct MedianFilter filter;
@@ -175,7 +174,6 @@ RCL_AddRefclock(RefclockParameters *params)
   inst->driver_parameter_length = 0;
   inst->driver_poll = params->driver_poll;
   inst->poll = params->poll;
-  inst->missed_samples = 0;
   inst->driver_polled = 0;
   inst->leap_status = 0;
   inst->pps_rate = params->pps_rate;
@@ -255,6 +253,7 @@ RCL_StartRefclocks(void)
   for (i = 0; i < n_sources; i++) {
     RCL_Instance inst = &refclocks[i];
 
+    SRC_SetSelectable(inst->source);
     inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
 
     if (inst->lock_ref) {
@@ -519,16 +518,13 @@ poll_timeout(void *arg)
       else
         stratum = 0;
 
-      SRC_SetReachable(inst->source);
+      SRC_UpdateReachability(inst->source, 1);
       SRC_AccumulateSample(inst->source, &sample_time, offset,
           inst->delay, dispersion, inst->delay, dispersion, stratum, inst->leap_status);
 
       log_sample(inst, &sample_time, 1, 0, 0.0, offset, dispersion);
-      inst->missed_samples = 0;
     } else {
-      inst->missed_samples++;
-      if (inst->missed_samples > 9)
-        SRC_UnsetReachable(inst->source);
+      SRC_UpdateReachability(inst->source, 0);
     }
   }
 
index 10e4295984777aa26c33571aba191ef36d14ee0a..0c0eb2c3002ea873f0b97e794807c66941aad485 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -90,9 +90,11 @@ struct SRC_Instance_Record {
                                    reference _it_ is sync'd to) */
   IPAddr *ip_addr;              /* Its IP address if NTP source */
 
-  /* Flag indicating that we are receiving packets with valid headers
-     from this source and can use it as a reference */
-  int reachable;
+  /* Flag indicating that we can use this source as a reference */
+  int selectable;
+
+  /* Reachability register */
+  int reachability;
 
   /* Flag indicating the status of the source */
   SRC_Status status;
@@ -127,6 +129,9 @@ static int selected_source_index; /* Which source index is currently
                                      selected (set to INVALID_SOURCE
                                      if no current valid reference) */
 
+/* Keep reachability status for last 8 samples */
+#define REACH_BITS 8
+
 /* ================================================== */
 /* Forward prototype */
 
@@ -196,7 +201,8 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, SRC_Sele
   result->leap_status = LEAP_Normal;
   result->ref_id = ref_id;
   result->ip_addr = addr;
-  result->reachable = 0;
+  result->selectable = 0;
+  result->reachability = 0;
   result->status = SRC_BAD_STATS;
   result->type = type;
   result->sel_option = sel_option;
@@ -218,10 +224,7 @@ void SRC_DestroyInstance(SRC_Instance instance)
 
   assert(initialised);
 
-  if (instance->index == selected_source_index) {
-    instance->reachable = 0;
-    SRC_SelectSource(0);
-  }
+  SRC_UnsetSelectable(instance);
 
   SST_DeleteInstance(instance->stats);
   dead_index = instance->index;
@@ -304,9 +307,9 @@ void SRC_AccumulateSample
 /* ================================================== */
 
 void
-SRC_SetReachable(SRC_Instance inst)
+SRC_SetSelectable(SRC_Instance inst)
 {
-  inst->reachable = 1;
+  inst->selectable = 1;
 
 #ifdef TRACEON
   LOG(LOGS_INFO, LOGF_Sources, "%s", source_to_string(inst));
@@ -319,9 +322,9 @@ SRC_SetReachable(SRC_Instance inst)
 /* ================================================== */
 
 void
-SRC_UnsetReachable(SRC_Instance inst)
+SRC_UnsetSelectable(SRC_Instance inst)
 {
-  inst->reachable = 0;
+  inst->selectable = 0;
 
 #ifdef TRACEON
   LOG(LOGS_INFO, LOGF_Sources, "%s%s", source_to_string(inst),
@@ -338,6 +341,30 @@ SRC_UnsetReachable(SRC_Instance inst)
 
 /* ================================================== */
 
+void
+SRC_UpdateReachability(SRC_Instance inst, int reachable)
+{
+  inst->reachability <<= 1;
+  inst->reachability |= !!reachable;
+  inst->reachability &= ~(-1 << REACH_BITS);
+
+  if (!reachable && inst->index == selected_source_index) {
+    /* Try to select a better source */
+    SRC_SelectSource(0);
+  }
+}
+
+/* ================================================== */
+
+void
+SRC_ResetReachability(SRC_Instance inst)
+{
+  inst->reachability = 0;
+  SRC_UpdateReachability(inst, 0);
+}
+
+/* ================================================== */
+
 static int
 compare_sort_elements(const void *a, const void *b)
 {
@@ -416,7 +443,8 @@ SRC_SelectSource(unsigned long match_addr)
   n_sel_sources = 0;
   for (i=0; i<n_sources; i++) {
 
-    if (sources[i]->reachable && sources[i]->sel_option != SRC_SelectNoselect) {
+    if (sources[i]->selectable && sources[i]->reachability &&
+        sources[i]->sel_option != SRC_SelectNoselect) {
 
       si = &(sources[i]->sel_info);
       SST_GetSelectionData(sources[i]->stats, &now,
index 4351e13c2edb1cbe8899124469c5c569ab74a183..ae7e3c72534eac9f7eb1b67168b1664cc8e4b46d 100644 (file)
--- a/sources.h
+++ b/sources.h
@@ -120,11 +120,17 @@ extern void SRC_AccumulateSample(SRC_Instance instance, struct timeval *sample_t
 
 /* This routine indicates that packets with valid headers are being
    received from the designated source */
-extern void SRC_SetReachable(SRC_Instance instance);
+extern void SRC_SetSelectable(SRC_Instance instance);
 
 /* This routine indicates that we are no longer receiving packets with
    valid headers from the designated source */
-extern void SRC_UnsetReachable(SRC_Instance instance);
+extern void SRC_UnsetSelectable(SRC_Instance instance);
+
+/* This routine updates the reachability register */
+extern void SRC_UpdateReachability(SRC_Instance inst, int reachable);
+
+/* This routine marks the source unreachable */
+extern void SRC_ResetReachability(SRC_Instance inst);
 
 /* This routine is used to select the best source from amongst those
    we currently have valid data on, and use it as the tracking base