]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Base poll adjustment on number of sourcestats samples
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 13 Oct 2010 14:49:28 +0000 (16:49 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Wed, 13 Oct 2010 14:49:28 +0000 (16:49 +0200)
Instead of following skew changes, adjust polling interval so that the
number of measurements used in the regression algorithm remains close to
a target value. It can be configured with a new polltarget option
(6 by default).

12 files changed:
chrony.texi
client.c
cmdmon.c
cmdparse.c
cmdparse.h
conf.c
ntp_core.c
sources.c
sources.h
sourcestats.c
sourcestats.h
srcparams.h

index beb6b40f72eebe5a0a7fe8b60d07081b29f47eed..f86a0ac0bb9579a67726831e7fa5c498f08afb22 100644 (file)
@@ -1861,8 +1861,8 @@ Local poll [10]
 Remote poll [10]
 @item
 `Score' (an internal score within each polling level used to decide when
-to increase or decrease the polling level.  This is adjusted based on
-changes to the variance of the measurements obtained from the source). [1]
+to increase or decrease the polling level.  This is adjusted based on number
+of measurements currently being used for the regression algorithm). [1.0]
 @item
 The estimated local clock error (`theta' in RFC1305).  Positive indicates that the local clock is slow. [-4.966e-03].
 @item
@@ -2629,6 +2629,12 @@ selecting that source.  This is useful with low stratum sources that are known
 to be unrealiable or inaccurate and which should be used only when other
 sources are unreachable.
 
+@item polltarget
+Target number of measurements to use for the regression algorithm which
+@code{chronyd} will try to maintain by adjusting polling interval between
+@code{minpoll} and @code{maxpoll}.  A higher target makes @code{chronyd} prefer
+shorter polling intervals.  The default is 6 and a useful range is 6 to 60.
+
 @item prefer
 Prefer this source over sources without prefer option.
 
index 2b7164e9fe9a59b30deeba23430f7ebdbc442732..c31564d2afc161bcf0b149b3c42da0a87eef4a6f 100644 (file)
--- a/client.c
+++ b/client.c
@@ -936,6 +936,11 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
         break;
       }
 
+      if (data.params.poll_target != SRC_DEFAULT_POLLTARGET) {
+        fprintf(stderr, "Option polltarget not supported\n");
+        break;
+      }
+
       msg->data.ntp_source.port = htonl((unsigned long) data.port);
       UTI_IPHostToNetwork(&data.ip_addr, &msg->data.ntp_source.ip_addr);
       msg->data.ntp_source.minpoll = htonl(data.params.minpoll);
@@ -983,6 +988,9 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
     case CPS_BadMinstratum:
       fprintf(stderr, "Unreadable minstratum value\n");
       break;
+    case CPS_BadPolltarget:
+      fprintf(stderr, "Unreadable polltarget value\n");
+      break;
   }
 
   return result;
index 1a1c10ea1c330bf6e79ff309d82bd7eefe393614..3b9fe193b31999532352cb54aaa3ed34fa1c3503 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -1251,6 +1251,7 @@ handle_add_source(NTP_Source_Type type, CMD_Request *rx_message, CMD_Reply *tx_m
 
  /* not transmitted in cmdmon protocol yet */
   params.min_stratum = SRC_DEFAULT_MINSTRATUM;       
+  params.poll_target = SRC_DEFAULT_POLLTARGET;
 
   status = NSR_AddSource(&rem_addr, type, &params);
   switch (status) {
index dca477f9956bae6f80b6007d545d4962f2b8e4b9..be4598941e936171c7c2ead2d47b0d95cf5a9c19 100644 (file)
@@ -60,6 +60,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
   src->params.auto_offline = 0;
   src->params.iburst = 0;
   src->params.min_stratum = SRC_DEFAULT_MINSTRATUM;
+  src->params.poll_target = SRC_DEFAULT_POLLTARGET;
   src->params.sel_option = SRC_SelectNormal;
 
   result = CPS_Success;
@@ -165,6 +166,15 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
             line += n;
           }
 
+        } else if (!strncasecmp(cmd, "polltarget", 10)) {
+          if (sscanf(line, "%d%n", &src->params.poll_target, &n) != 1) {
+            result = CPS_BadPolltarget;
+            ok = 0;
+            done = 1;
+          } else {
+            line += n;
+          }
+
         } else if (!strncasecmp(cmd, "noselect", 8)) {
           src->params.sel_option = SRC_SelectNoselect;
         
index 9f4d4ae5d790dade3d0ab1b1732f8703d4d50bb3..a6353bd53b8373708a4e9e95e6c52f5595395e21 100644 (file)
@@ -45,7 +45,8 @@ typedef enum {
   CPS_BadMaxdelayratio,
   CPS_BadMaxdelay,
   CPS_BadKey,
-  CPS_BadMinstratum
+  CPS_BadMinstratum,
+  CPS_BadPolltarget
 } CPS_Status;
 
 typedef struct {
diff --git a/conf.c b/conf.c
index 552a5fd049bb4313fa5da34371c6c619c27e43ce..5bfd3264f7eb164bf87ff5fc264a7a65710421d5 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -397,6 +397,9 @@ parse_source(const char *line, NTP_Source_Type type)
     case CPS_BadMinstratum:
       LOG(LOGS_WARN, LOGF_Configure, "Unreadable minstratum value at line %d", line_number);
       break;
+    case CPS_BadPolltarget:
+      LOG(LOGS_WARN, LOGF_Configure, "Unreadable polltarget value at line %d", line_number);
+      break;
   }
 
   return;
index 7f8d3ca0b24f7a13a57abc2d0a3aa1821b9219b8..62148cb845b26d9027a6c0f6598e47cd92ed6849 100644 (file)
@@ -55,10 +55,6 @@ static LOG_FileID logfileid;
 /* Day number of 1 Jan 1970 */
 #define MJD_1970 40587
 
-/* ================================================== */
-
-#define ZONE_WIDTH 4
-
 /* ================================================== */
 /* Enumeration used for remembering the operating mode of one of the
    sources */
@@ -110,6 +106,10 @@ struct NCR_Instance_Record {
   int min_stratum;              /* Increase stratum in received packets to the
                                    minimum */
 
+  int poll_target;              /* Target number of sourcestats samples */
+
+  double poll_score;            /* Score of current local poll */
+
   double max_delay;             /* Maximum round-trip delay to the
                                    peer that we can tolerate and still
                                    use the sample for generating
@@ -163,8 +163,6 @@ struct NCR_Instance_Record {
 
   SRC_Instance source;
 
-  int score;
-
   int burst_good_samples_to_go;
   int burst_total_samples_to_go;
 
@@ -215,7 +213,7 @@ void
 NCR_Initialise(void)
 {
   logfileid = CNF_GetLogMeasurements() ? LOG_FileOpen("measurements",
-      "   Date (UTC) Time     IP Address   L St 1234 ab 5678 LP RP S Offset     Peer del. Peer disp. Root del.  Root disp.")
+      "   Date (UTC) Time     IP Address   L St 1234 ab 5678 LP RP Score Offset     Peer del. Peer disp. Root del.  Root disp.")
     : -1;
 
   access_auth_table = ADF_CreateTable();
@@ -292,7 +290,8 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
   result->remote_orig.hi = 0;
   result->remote_orig.lo = 0;
 
-  result->score = 0;
+  result->poll_target = params->poll_target;
+  result->poll_score = 0.0;
 
   if (params->online) {
     start_initial_timeout(result);
@@ -448,29 +447,28 @@ check_packet_auth(NTP_Packet *pkt, unsigned long keyid)
 /* ================================================== */
 
 static void
-normalise_score(NCR_Instance inst)
+adjust_poll(NCR_Instance inst, double adj)
 {
+  inst->poll_score += adj;
 
-  while (inst->score >= ZONE_WIDTH) {
-    ++inst->local_poll;
-    inst->score -= ZONE_WIDTH;
+  if (inst->poll_score >= 1.0) {
+    inst->local_poll += (int)inst->poll_score;
+    inst->poll_score -= (int)inst->poll_score;
   }
-  while (inst->score < 0) {
-    if (inst->local_poll > 0) {
-      --inst->local_poll;
-    }
-    inst->score += ZONE_WIDTH;
+
+  if (inst->poll_score < 0.0) {
+    inst->local_poll += (int)(inst->poll_score - 1.0);
+    inst->poll_score -= (int)(inst->poll_score - 1.0);
   }
   
   /* Clamp polling interval to defined range */
   if (inst->local_poll < inst->minpoll) {
     inst->local_poll = inst->minpoll;
-    inst->score = 0;
+    inst->poll_score = 0;
   } else if (inst->local_poll > inst->maxpoll) {
     inst->local_poll = inst->maxpoll;
-    inst->score = ZONE_WIDTH - 1;
+    inst->poll_score = 1.0;
   }
-
 }
 
 /* ================================================== */
@@ -652,13 +650,11 @@ transmit_timeout(void *arg)
   if (SRC_IsSyncPeer(inst->source)) {
     if (inst->tx_count >= 2) {
       /* Implies we have missed at least one transmission */
-      inst->score -= 3;
-      normalise_score(inst);
+      adjust_poll(inst, -0.75);
     }
   } else {
     if (inst->tx_count >= 2) {
-      inst->score += 1;
-      normalise_score(inst);
+      adjust_poll(inst, 0.25);
     }
   }
 
@@ -810,7 +806,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
   int poll_to_use;
   double delay_time = 0;
   int requeue_transmit = 0;
-  int delta_score;
+  double poll_adj;
 
   /* ==================== */
 
@@ -1089,31 +1085,22 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
         temp>>=1;
       } while (temp);
       
-      inst->local_poll -= shift;
-      inst->score = 0;
+      poll_adj = -shift - inst->poll_score + 0.5;
       
     } else {
+      int samples = SRC_Samples(inst->source);
 
-      switch (SRC_LastSkewChange(inst->source)) {
-        case SRC_Skew_Decrease:
-          delta_score = 1;
-          break;
-        case SRC_Skew_Nochange:
-          delta_score = 0;
-          break;
-        case SRC_Skew_Increase:
-          delta_score = -2;
-          break;
-        default: /* Should not happen! */
-          delta_score = 0;
-          break;
-      }      
+      /* Adjust polling interval so that the number of sourcestats samples
+         remains close to the target value */
+      poll_adj = ((double)samples / inst->poll_target - 1.0) / inst->poll_target;
 
-      inst->score += delta_score;
+      /* Use higher gain when decreasing the interval */
+      if (samples < inst->poll_target) {
+        poll_adj *= 2.0;
+      }
     }
 
-    normalise_score(inst);
-
+    adjust_poll(inst, poll_adj);
   }
 
   /* Reduce polling rate if KoD RATE was received */
@@ -1253,7 +1240,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
 
   /* Do measurement logging */
   if (logfileid != -1) {
-    LOG_FileWrite(logfileid, "%s %-15s %1c %2d %1d%1d%1d%1d %1d%1d %1d%1d%1d%1d %2d %2d %2d %10.3e %10.3e %10.3e %10.3e %10.3e",
+    LOG_FileWrite(logfileid, "%s %-15s %1c %2d %1d%1d%1d%1d %1d%1d %1d%1d%1d%1d %2d %2d %4.2f %10.3e %10.3e %10.3e %10.3e %10.3e",
             UTI_TimeToLogForm(sample_time.tv_sec),
             UTI_IPToString(&inst->remote_addr.ip_addr),
             sync_stats[pkt_leap],
@@ -1262,7 +1249,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
             test4a, test4b,
             test5, test6, test7, test8,
             inst->local_poll, inst->remote_poll,
-            (inst->score),
+            inst->poll_score,
             theta, delta, epsilon,
             pkt_root_delay, pkt_root_dispersion);
   }            
@@ -1668,7 +1655,7 @@ NCR_TakeSourceOnline(NCR_Instance inst)
         /* We are not already actively polling it */
         LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToString(&inst->remote_addr.ip_addr));
         inst->local_poll = inst->minpoll;
-        inst->score = (ZONE_WIDTH >> 1);
+        inst->poll_score = 0.5;
         inst->opmode = MD_ONLINE;
         start_initial_timeout(inst);
       }
index a019890176eea4759b03b78206f89e1527d3e6b9..38706cac76adcaa91386732b01c41645f9b56876 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -1027,3 +1027,11 @@ SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst)
 }
 
 /* ================================================== */
+
+int
+SRC_Samples(SRC_Instance inst)
+{
+  return SST_Samples(inst->stats);
+}
+
+/* ================================================== */
index aff800a97c59c6411e76d0ebf9fd9664ac5a1775..d89ce597a979e79bd155bb835a9641d6b11598c9 100644 (file)
--- a/sources.h
+++ b/sources.h
@@ -165,5 +165,7 @@ typedef enum {
 
 extern SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst);
 
+extern int SRC_Samples(SRC_Instance inst);
+
 #endif /* GOT_SOURCES_H */
 
index bcd818e116c766024508dcdb77bdb11adbe6614f..652421fc55de435ba3ff90b9c2dead418ac08f36 100644 (file)
@@ -789,6 +789,14 @@ SST_Skew_Direction SST_LastSkewChange(SST_Stats inst)
 
 /* ================================================== */
 
+int
+SST_Samples(SST_Stats inst)
+{
+  return inst->n_samples;
+}
+
+/* ================================================== */
+
 void
 SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct timeval *now)
 {
index c48af7b7e842c48849e359874ee9bd2d74cd5d6b..e47287f79cb3f9a08da756109886640ecaceb01f 100644 (file)
@@ -153,5 +153,7 @@ typedef enum {
 
 extern SST_Skew_Direction SST_LastSkewChange(SST_Stats inst);
 
+extern int SST_Samples(SST_Stats inst);
+
 #endif /* GOT_SOURCESTATS_H */
 
index 9db3806a26385af48e4cf2b71d34d30a08f53df4..58395cb43d9e35c904ba837c4e7767bb63578a43 100644 (file)
@@ -41,6 +41,7 @@ typedef struct {
   int presend_minpoll;
   int iburst;
   int min_stratum;
+  int poll_target;
   unsigned long authkey;
   double max_delay;
   double max_delay_ratio;
@@ -54,6 +55,7 @@ typedef struct {
 #define SRC_DEFAULT_MAXDELAY 16.0
 #define SRC_DEFAULT_MAXDELAYRATIO 16384.0
 #define SRC_DEFAULT_MINSTRATUM 0
+#define SRC_DEFAULT_POLLTARGET 6
 #define INACTIVE_AUTHKEY 0UL
 
 #endif /* GOT_SRCPARAMS_H */