From d3fe9602714e01b228fa0c625901e748912a7775 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 27 Sep 2014 22:56:09 +0200 Subject: [PATCH] ntpd: be less eager to use shorter poll intervals * 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 --- networking/ntpd.c | 80 ++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 2d1ad69a0..b2b2791a8 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: ; } -- 2.25.1