[PATCH] ntpd: don't stay at short polling interval

Miroslav Lichvar mlichvar at redhat.com
Wed Oct 1 13:51:30 UTC 2014


To avoid polling servers frequently slowly increase the interval up
to BIGPOLL when
- no replies are received from a peer
- no source can be selected
- peer claims to be unsynchronized (e.g. we are polling it too
  frequently)
- recv() returns with an error (e.g. the host doesn't exist or is not
  running an NTP service)

Signed-off-by: Miroslav Lichvar <mlichvar at redhat.com>
---
 networking/ntpd.c | 37 ++++++++++++++++++++++++++++---------
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/networking/ntpd.c b/networking/ntpd.c
index b2b2791..d8df125 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -1730,6 +1730,7 @@ recv_and_process_peer_pkt(peer_t *p)
 	datapoint_t *datapoint;
 	peer_t      *q;
 
+	rc = 0;
 	offset = 0;
 
 	/* We can recvfrom here and check from.IP, but some multihomed
@@ -1744,9 +1745,8 @@ recv_and_process_peer_pkt(peer_t *p)
 		 || errno == ECONNREFUSED || errno == EADDRNOTAVAIL
 		 || errno == EAGAIN
 		) {
-//TODO: always do this?
-			interval = poll_interval(RETRY_INTERVAL);
-			goto set_next_and_ret;
+			rc = 1;
+			goto pick_normal_interval;
 		}
 		xfunc_die();
 	}
@@ -1778,6 +1778,7 @@ recv_and_process_peer_pkt(peer_t *p)
 // "DENY", "RSTR" - peer does not like us at all
 // "RATE" - peer is overloaded, reduce polling freq
 		bb_error_msg("reply from %s: peer is unsynced", p->p_dotted);
+		rc = 1;
 		goto pick_normal_interval;
 	}
 
@@ -1866,9 +1867,8 @@ recv_and_process_peer_pkt(peer_t *p)
 	/* Muck with statictics and update the clock */
 	filter_datapoints(p);
 	q = select_and_cluster();
-	rc = -1;
+	rc = 1;
 	if (q) {
-		rc = 0;
 		if (!(option_mask32 & OPT_w)) {
 			rc = update_local_clock(q);
 			/* If drift is dangerously large, immediately
@@ -1880,10 +1880,15 @@ recv_and_process_peer_pkt(peer_t *p)
 				rc = 0;
 			}
 		}
+	} else {
+		/* Keep increasing the polling interval when no source can be
+		 * selected, but wait until the initial burst is complete.
+		 */
+		if (!G.initial_poll_complete)
+			rc = 0;
 	}
-	/* else: no peer selected, rc = -1: we want to poll more often */
 
-	if (rc != 0) {
+	if (q && rc != 0) {
 		/* Adjust the poll interval by comparing the current offset
 		 * with the clock jitter. If the offset is less than
 		 * the clock jitter times a constant, then the averaging interval
@@ -1897,10 +1902,18 @@ recv_and_process_peer_pkt(peer_t *p)
 		} else {
 			adjust_poll(-G.poll_exp * 2);
 		}
+		rc = 0;
 	}
 
-	/* Decide when to send new query for this peer */
+	/* Decide when to send new query for this peer. When recv() is failing,
+	 * no peer can be selected or the peer is unsynchronized, slowly
+	 * increase the polling interval up to BIGPOLL to not overload the peer
+	 * or the network.
+	 */
  pick_normal_interval:
+	if (rc > 0 && G.poll_exp < BIGPOLL)
+		adjust_poll(POLLADJ_LIMIT / 8);
+
 	interval = poll_interval(INT_MAX);
 	if (fabs(offset) >= BIGOFF && interval > BIGOFF_INTERVAL) {
 		/* If we are synced, offsets are less than STEP_THRESHOLD,
@@ -1917,7 +1930,6 @@ recv_and_process_peer_pkt(peer_t *p)
 		interval = BIGOFF_INTERVAL;
 	}
 
- set_next_and_ret:
 	set_next(p, interval);
 }
 
@@ -2252,6 +2264,13 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
 					/* Timed out waiting for reply */
 					close(p->p_fd);
 					p->p_fd = -1;
+
+					/* Slowly increase the polling interval up to BIGPOLL
+					 * in case the network or the peer is overloaded.
+					 */
+					if (G.poll_exp < BIGPOLL)
+						adjust_poll(POLLADJ_LIMIT / 8);
+
 					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);
-- 
1.9.3



More information about the busybox mailing list