[git commit] ntpd: be less eager to use shorter poll intervals

Denys Vlasenko vda.linux at googlemail.com
Sat Sep 27 20:56:09 UTC 2014


commit: http://git.busybox.net/busybox/commit/?id=d3fe9602714e01b228fa0c625901e748912a7775
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

* on step, poll interval drops to 8.5 mins instead of 32 seconds
* on total loss of all replies (no replies from any peer
  for last 8 requests), also drop poll interval to 8.5 mins
  instead of 32 seconds
* on send abd recv errors, RETRY_INTERVAL is now 32 seconds,
  not 5 seconds
* on timing out listening to reply, instead of unconditional
  shortening poll interval by x4, clamp it to NOREPLY_INTERVAL
  (512 seconds)
* if a largish offset is seen, clamp nexp poll interval
  to 128 seconds, not 64 seconds

function                                             old     new   delta
clamp_pollexp_and_set_MAXSTRAT                         -      37     +37
recv_and_process_peer_pkt                            861     869      +8
poll_interval                                         52      48      -4
update_local_clock                                   762     752     -10
ntpd_main                                           1063    1050     -13
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/3 up/down: 45/-27)             Total: 18 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/ntpd.c |   80 +++++++++++++++++++++++++++--------------------------
 1 files changed, 41 insertions(+), 39 deletions(-)

diff --git a/networking/ntpd.c b/networking/ntpd.c
index 2d1ad69..b2b2791 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -109,35 +109,43 @@
  *   datapoints after the step.
  */
 
-#define RETRY_INTERVAL     5    /* on error, retry in N secs */
-#define RESPONSE_INTERVAL 15    /* wait for reply up to N secs */
 #define INITIAL_SAMPLES    4    /* how many samples do we want for init */
 #define BAD_DELAY_GROWTH   4    /* drop packet if its delay grew by more than this */
 
-/* Clock discipline parameters and constants */
+#define RETRY_INTERVAL    32    /* on send/recv error, retry in N secs (need to be power of 2) */
+#define NOREPLY_INTERVAL 512    /* sent, but got no reply: cap next query by this many seconds */
+#define RESPONSE_INTERVAL 16    /* wait for reply up to N secs */
 
 /* Step threshold (sec). std ntpd uses 0.128.
- * Using exact power of 2 (1/8) results in smaller code */
+ * Using exact power of 2 (1/8) results in smaller code
+ */
 #define STEP_THRESHOLD  0.125
-#define WATCH_THRESHOLD 128     /* stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */
+/* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */
+#define WATCH_THRESHOLD 128
 /* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */
 //UNUSED: #define PANIC_THRESHOLD 1000    /* panic threshold (sec) */
 
+/*
+ * If we got |offset| > BIGOFF from a peer, cap next query interval
+ * for this peer by this many seconds:
+ */
+#define BIGOFF          (STEP_THRESHOLD * 8)
+#define BIGOFF_INTERVAL (1 << 7) /* 128 s */
+
 #define FREQ_TOLERANCE  0.000015 /* frequency tolerance (15 PPM) */
 #define BURSTPOLL       0       /* initial poll */
 #define MINPOLL         5       /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */
-/* If we got largish offset from a peer, cap next query interval
- * for this peer by this many seconds:
- */
-#define BIGOFF_INTERVAL (1 << 6)
-/* If offset > discipline_jitter * POLLADJ_GATE, and poll interval is >= 2^BIGPOLL,
+/*
+ * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is >= 2^BIGPOLL,
  * then it is decreased _at once_. (If < 2^BIGPOLL, it will be decreased _eventually_).
  */
 #define BIGPOLL         10      /* 2^10 sec ~= 17 min */
 #define MAXPOLL         12      /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */
-/* Actively lower poll when we see such big offsets.
+/*
+ * Actively lower poll when we see such big offsets.
  * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively
- * if offset increases over ~0.04 sec */
+ * if offset increases over ~0.04 sec
+ */
 #define POLLDOWN_OFFSET (STEP_THRESHOLD / 3)
 #define MINDISP         0.01    /* minimum dispersion (sec) */
 #define MAXDISP         16      /* maximum dispersion (sec) */
@@ -972,6 +980,16 @@ step_time(double offset)
 	}
 }
 
+static void clamp_pollexp_and_set_MAXSTRAT(void)
+{
+	if (G.poll_exp < MINPOLL)
+		G.poll_exp = MINPOLL;
+	if (G.poll_exp >= BIGPOLL)
+		G.poll_exp = BIGPOLL - 1;
+	G.polladj_count = 0;
+	G.stratum = MAXSTRAT;
+}
+
 
 /*
  * Selection and clustering, and their helpers
@@ -1453,9 +1471,7 @@ update_local_clock(peer_t *p)
 			exit(0);
 		}
 
-		G.polladj_count = 0;
-		G.poll_exp = MINPOLL;
-		G.stratum = MAXSTRAT;
+		clamp_pollexp_and_set_MAXSTRAT();
 
 		run_script("step", offset);
 
@@ -1654,28 +1670,16 @@ update_local_clock(peer_t *p)
  * (helpers first)
  */
 static unsigned
-retry_interval(void)
-{
-	/* Local problem, want to retry soon */
-	unsigned interval, r;
-	interval = RETRY_INTERVAL;
-	r = rand();
-	interval += r % (unsigned)(RETRY_INTERVAL / 4);
-	VERB4 bb_error_msg("chose retry interval:%u", interval);
-	return interval;
-}
-static unsigned
-poll_interval(int exponent)
+poll_interval(int upper_bound)
 {
 	unsigned interval, r, mask;
-	exponent = G.poll_exp + exponent;
-	if (exponent < 0)
-		exponent = 0;
-	interval = 1 << exponent;
+	interval = 1 << G.poll_exp;
+	if (interval > upper_bound)
+		interval = upper_bound;
 	mask = ((interval-1) >> 4) | 1;
 	r = rand();
 	interval += r & mask; /* ~ random(0..1) * interval/16 */
-	VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d exp:%d)", interval, G.poll_exp, exponent);
+	VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d)", interval, G.poll_exp);
 	return interval;
 }
 static NOINLINE void
@@ -1741,7 +1745,7 @@ recv_and_process_peer_pkt(peer_t *p)
 		 || errno == EAGAIN
 		) {
 //TODO: always do this?
-			interval = retry_interval();
+			interval = poll_interval(RETRY_INTERVAL);
 			goto set_next_and_ret;
 		}
 		xfunc_die();
@@ -1897,8 +1901,8 @@ recv_and_process_peer_pkt(peer_t *p)
 
 	/* Decide when to send new query for this peer */
  pick_normal_interval:
-	interval = poll_interval(0);
-	if (fabs(offset) >= STEP_THRESHOLD * 8 && interval > BIGOFF_INTERVAL) {
+	interval = poll_interval(INT_MAX);
+	if (fabs(offset) >= BIGOFF && interval > BIGOFF_INTERVAL) {
 		/* If we are synced, offsets are less than STEP_THRESHOLD,
 		 * or at the very least not much larger than it.
 		 * Now we see a largish one.
@@ -2248,7 +2252,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
 					/* Timed out waiting for reply */
 					close(p->p_fd);
 					p->p_fd = -1;
-					timeout = poll_interval(-2); /* -2: try a bit sooner */
+					timeout = poll_interval(NOREPLY_INTERVAL);
 					bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us",
 							p->p_dotted, p->reachable_bits, timeout);
 					set_next(p, timeout);
@@ -2339,9 +2343,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
 					goto have_reachable_peer;
 			}
 			/* No peer responded for last 8 packets, panic */
-			G.polladj_count = 0;
-			G.poll_exp = MINPOLL;
-			G.stratum = MAXSTRAT;
+			clamp_pollexp_and_set_MAXSTRAT();
 			run_script("unsync", 0.0);
  have_reachable_peer: ;
 		}


More information about the busybox-cvs mailing list