summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-01-11 02:14:04 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-01-11 02:14:04 +0100
commit65d722bb0d0e822db014a742da4c9c2c111131f0 (patch)
tree2d4d1841cdd04dd1aca55194c9a9ab33b683c92d
parent12628b77970b46290ed75ecae55afe65297b3e35 (diff)
ntpd: explain algorithm
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/ntpd.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 092c444d4..e52d20c01 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -46,8 +46,34 @@
#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) */
@@ -75,8 +101,9 @@
* 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;