ntpd: explain algorithm
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 11 Jan 2010 01:14:04 +0000 (02:14 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 11 Jan 2010 01:14:04 +0000 (02:14 +0100)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/ntpd.c

index 092c444d477124e9841757ef0da7241051526b6a..e52d20c01fce9a26926cb64e1a54c59fea4acb64 100644 (file)
 #define MAX_VERBOSE     2
 
 
+/* High-level description of the algorithm:
+ *
+ * We start running with very small poll_exp, BURSTPOLL,
+ * in order to quickly accumulate INITIAL_SAMLPES datapoints
+ * for each peer. Then, time is stepped if the offset is larger
+ * than STEP_THRESHOLD, otherwise it isn't; anyway, we enlarge
+ * poll_exp to MINPOLL and enter frequency measurement step:
+ * we collect new datapoints but ignore them for WATCH_THRESHOLD
+ * seconds. After WATCH_THRESHOLD seconds we look at accumulated
+ * offset and estimate frequency drift.
+ *
+ * After this, we enter "steady state": we collect a datapoint,
+ * we select the best peer, if this datapoint is not a new one
+ * (IOW: if this datapoint isn't for selected peer), sleep
+ * and collect another one; otherwise, use its offset to update
+ * frequency drift, if offset is somewhat large, reduce poll_exp,
+ * otherwise increase poll_exp.
+ *
+ * If offset is larger than STEP_THRESHOLD, which shouldn't normally
+ * happen, we assume that something "bad" happened (computer
+ * was hibernated, someone set totally wrong date, etc),
+ * then the time is stepped, all datapoints are discarded,
+ * and we go back to steady state.
+ */
+
 #define RETRY_INTERVAL  5       /* on error, retry in N secs */
 #define RESPONSE_INTERVAL 15    /* wait for reply up to N secs */
+#define INITIAL_SAMLPES 4       /* how many samples do we want for init */
 
 /* Clock discipline parameters and constants */
 #define STEP_THRESHOLD  0.128   /* step threshold (s) */
  * we grow a counter: += MINPOLL. When it goes over POLLADJ_LIMIT,
  * we poll_exp++. If offset isn't small, counter -= poll_exp*2,
  * and when it goes below -POLLADJ_LIMIT, we poll_exp--
+ * (bumped from 30 to 36 since otherwise I often see poll_exp going *2* steps down)
  */
-#define POLLADJ_LIMIT   30
+#define POLLADJ_LIMIT   36
 /* If offset < POLLADJ_GATE * discipline_jitter, then we can increase
  * poll interval (we think we can't improve timekeeping
  * by staying at smaller poll).
@@ -1555,6 +1582,7 @@ recv_and_process_peer_pkt(peer_t *p)
                        if (q->filter_offset < -POLLDOWN_OFFSET
                         || q->filter_offset > POLLDOWN_OFFSET
                        ) {
+                               VERB3 bb_error_msg("offset:%f > POLLDOWN_OFFSET", q->filter_offset);
                                goto poll_down;
                        }
                }
@@ -1856,13 +1884,14 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
        idx2peer = xzalloc(sizeof(idx2peer[0]) * cnt);
        pfd = xzalloc(sizeof(pfd[0]) * cnt);
 
-       /* Countdown: we never sync before we sent 5 packets to each peer
+       /* Countdown: we never sync before we sent INITIAL_SAMLPES+1
+        * packets to each peer.
         * NB: if some peer is not responding, we may end up sending
         * fewer packets to it and more to other peers.
-        * NB2: sync usually happens using 5-1=4 packets, since last reply
-        * does not come back instantaneously.
+        * NB2: sync usually happens using INITIAL_SAMLPES packets,
+        * since last reply does not come back instantaneously.
         */
-       cnt = G.peer_cnt * 5;
+       cnt = G.peer_cnt * (INITIAL_SAMLPES + 1);
 
        while (!bb_got_signal) {
                llist_t *item;