aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiroslav Lichvar <mlichvar@redhat.com>2014-10-02 17:18:43 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2014-10-02 17:24:34 +0200
commitb434ce70696879aad066fff67253e44e5f5b238e (patch)
treeb29fa99983269a0ccd448d3ba8b6eba8b4dace93
parentcf76b5ce12a685b0c0a8ea53fa95cb0f0922a4f1 (diff)
downloadbusybox-w32-b434ce70696879aad066fff67253e44e5f5b238e.tar.gz
busybox-w32-b434ce70696879aad066fff67253e44e5f5b238e.tar.bz2
busybox-w32-b434ce70696879aad066fff67253e44e5f5b238e.zip
ntpd: don't stay at short polling interval
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) When recv() returns with an error, drop code to try to continue on network errors: I'm not convinced those cases happen in real life. function old new delta recv_and_process_peer_pkt 919 838 -81 Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/ntpd.c80
1 files changed, 53 insertions, 27 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
index b2b2791a8..838a367fe 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -136,17 +136,17 @@
136#define BURSTPOLL 0 /* initial poll */ 136#define BURSTPOLL 0 /* initial poll */
137#define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */ 137#define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */
138/* 138/*
139 * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is >= 2^BIGPOLL, 139 * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is > 2^BIGPOLL,
140 * then it is decreased _at once_. (If < 2^BIGPOLL, it will be decreased _eventually_). 140 * then it is decreased _at once_. (If <= 2^BIGPOLL, it will be decreased _eventually_).
141 */ 141 */
142#define BIGPOLL 10 /* 2^10 sec ~= 17 min */ 142#define BIGPOLL 9 /* 2^9 sec ~= 8.5 min */
143#define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */ 143#define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */
144/* 144/*
145 * Actively lower poll when we see such big offsets. 145 * Actively lower poll when we see such big offsets.
146 * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively 146 * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively
147 * if offset increases over ~0.04 sec 147 * if offset increases over ~0.04 sec
148 */ 148 */
149#define POLLDOWN_OFFSET (STEP_THRESHOLD / 3) 149//#define POLLDOWN_OFFSET (STEP_THRESHOLD / 3)
150#define MINDISP 0.01 /* minimum dispersion (sec) */ 150#define MINDISP 0.01 /* minimum dispersion (sec) */
151#define MAXDISP 16 /* maximum dispersion (sec) */ 151#define MAXDISP 16 /* maximum dispersion (sec) */
152#define MAXSTRAT 16 /* maximum stratum (infinity metric) */ 152#define MAXSTRAT 16 /* maximum stratum (infinity metric) */
@@ -984,8 +984,8 @@ static void clamp_pollexp_and_set_MAXSTRAT(void)
984{ 984{
985 if (G.poll_exp < MINPOLL) 985 if (G.poll_exp < MINPOLL)
986 G.poll_exp = MINPOLL; 986 G.poll_exp = MINPOLL;
987 if (G.poll_exp >= BIGPOLL) 987 if (G.poll_exp > BIGPOLL)
988 G.poll_exp = BIGPOLL - 1; 988 G.poll_exp = BIGPOLL;
989 G.polladj_count = 0; 989 G.polladj_count = 0;
990 G.stratum = MAXSTRAT; 990 G.stratum = MAXSTRAT;
991} 991}
@@ -1682,7 +1682,7 @@ poll_interval(int upper_bound)
1682 VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d)", interval, G.poll_exp); 1682 VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d)", interval, G.poll_exp);
1683 return interval; 1683 return interval;
1684} 1684}
1685static NOINLINE void 1685static void
1686adjust_poll(int count) 1686adjust_poll(int count)
1687{ 1687{
1688 G.polladj_count += count; 1688 G.polladj_count += count;
@@ -1693,7 +1693,7 @@ adjust_poll(int count)
1693 VERB4 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d", 1693 VERB4 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d",
1694 G.discipline_jitter, G.poll_exp); 1694 G.discipline_jitter, G.poll_exp);
1695 } 1695 }
1696 } else if (G.polladj_count < -POLLADJ_LIMIT || (count < 0 && G.poll_exp >= BIGPOLL)) { 1696 } else if (G.polladj_count < -POLLADJ_LIMIT || (count < 0 && G.poll_exp > BIGPOLL)) {
1697 G.polladj_count = 0; 1697 G.polladj_count = 0;
1698 if (G.poll_exp > MINPOLL) { 1698 if (G.poll_exp > MINPOLL) {
1699 llist_t *item; 1699 llist_t *item;
@@ -1736,19 +1736,23 @@ recv_and_process_peer_pkt(peer_t *p)
1736 * ntp servers reply from their *other IP*. 1736 * ntp servers reply from their *other IP*.
1737 * TODO: maybe we should check at least what we can: from.port == 123? 1737 * TODO: maybe we should check at least what we can: from.port == 123?
1738 */ 1738 */
1739 recv_again:
1739 size = recv(p->p_fd, &msg, sizeof(msg), MSG_DONTWAIT); 1740 size = recv(p->p_fd, &msg, sizeof(msg), MSG_DONTWAIT);
1740 if (size == -1) { 1741 if (size < 0) {
1741 bb_perror_msg("recv(%s) error", p->p_dotted); 1742 if (errno == EINTR)
1742 if (errno == EHOSTUNREACH || errno == EHOSTDOWN 1743 /* Signal caught */
1743 || errno == ENETUNREACH || errno == ENETDOWN 1744 goto recv_again;
1744 || errno == ECONNREFUSED || errno == EADDRNOTAVAIL 1745 if (errno == EAGAIN)
1745 || errno == EAGAIN 1746 /* There was no packet after all
1746 ) { 1747 * (poll() returning POLLIN for a fd
1747//TODO: always do this? 1748 * is not a ironclad guarantee that data is there)
1748 interval = poll_interval(RETRY_INTERVAL); 1749 */
1749 goto set_next_and_ret; 1750 return;
1750 } 1751 /*
1751 xfunc_die(); 1752 * If you need a different handling for a specific
1753 * errno, always explain it in comment.
1754 */
1755 bb_perror_msg_and_die("recv(%s) error", p->p_dotted);
1752 } 1756 }
1753 1757
1754 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { 1758 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
@@ -1774,10 +1778,15 @@ recv_and_process_peer_pkt(peer_t *p)
1774 || msg.m_stratum == 0 1778 || msg.m_stratum == 0
1775 || msg.m_stratum > NTP_MAXSTRATUM 1779 || msg.m_stratum > NTP_MAXSTRATUM
1776 ) { 1780 ) {
1777// TODO: stratum 0 responses may have commands in 32-bit m_refid field:
1778// "DENY", "RSTR" - peer does not like us at all
1779// "RATE" - peer is overloaded, reduce polling freq
1780 bb_error_msg("reply from %s: peer is unsynced", p->p_dotted); 1781 bb_error_msg("reply from %s: peer is unsynced", p->p_dotted);
1782 /*
1783 * Stratum 0 responses may have commands in 32-bit m_refid field:
1784 * "DENY", "RSTR" - peer does not like us at all,
1785 * "RATE" - peer is overloaded, reduce polling freq.
1786 * If poll interval is small, increase it.
1787 */
1788 if (G.poll_exp < BIGPOLL)
1789 goto increase_interval;
1781 goto pick_normal_interval; 1790 goto pick_normal_interval;
1782 } 1791 }
1783 1792
@@ -1866,11 +1875,19 @@ recv_and_process_peer_pkt(peer_t *p)
1866 /* Muck with statictics and update the clock */ 1875 /* Muck with statictics and update the clock */
1867 filter_datapoints(p); 1876 filter_datapoints(p);
1868 q = select_and_cluster(); 1877 q = select_and_cluster();
1869 rc = -1; 1878 rc = 0;
1870 if (q) { 1879 if (q) {
1871 rc = 0;
1872 if (!(option_mask32 & OPT_w)) { 1880 if (!(option_mask32 & OPT_w)) {
1873 rc = update_local_clock(q); 1881 rc = update_local_clock(q);
1882#if 0
1883//Disabled this because there is a case where largish offsets
1884//are unavoidable: if network round-trip delay is, say, ~0.6s,
1885//error in offset estimation would be ~delay/2 ~= 0.3s.
1886//Thus, offsets will be usually in -0.3...0.3s range.
1887//In this case, this code would keep poll interval small,
1888//but it won't be helping.
1889//BIGOFF check below deals with a case of seeing multi-second offsets.
1890
1874 /* If drift is dangerously large, immediately 1891 /* If drift is dangerously large, immediately
1875 * drop poll interval one step down. 1892 * drop poll interval one step down.
1876 */ 1893 */
@@ -1879,9 +1896,15 @@ recv_and_process_peer_pkt(peer_t *p)
1879 adjust_poll(-POLLADJ_LIMIT * 3); 1896 adjust_poll(-POLLADJ_LIMIT * 3);
1880 rc = 0; 1897 rc = 0;
1881 } 1898 }
1899#endif
1882 } 1900 }
1901 } else {
1902 /* No peer selected.
1903 * If poll interval is small, increase it.
1904 */
1905 if (G.poll_exp < BIGPOLL)
1906 goto increase_interval;
1883 } 1907 }
1884 /* else: no peer selected, rc = -1: we want to poll more often */
1885 1908
1886 if (rc != 0) { 1909 if (rc != 0) {
1887 /* Adjust the poll interval by comparing the current offset 1910 /* Adjust the poll interval by comparing the current offset
@@ -1893,6 +1916,7 @@ recv_and_process_peer_pkt(peer_t *p)
1893 if (rc > 0 && G.offset_to_jitter_ratio <= POLLADJ_GATE) { 1916 if (rc > 0 && G.offset_to_jitter_ratio <= POLLADJ_GATE) {
1894 /* was += G.poll_exp but it is a bit 1917 /* was += G.poll_exp but it is a bit
1895 * too optimistic for my taste at high poll_exp's */ 1918 * too optimistic for my taste at high poll_exp's */
1919 increase_interval:
1896 adjust_poll(MINPOLL); 1920 adjust_poll(MINPOLL);
1897 } else { 1921 } else {
1898 adjust_poll(-G.poll_exp * 2); 1922 adjust_poll(-G.poll_exp * 2);
@@ -1917,7 +1941,6 @@ recv_and_process_peer_pkt(peer_t *p)
1917 interval = BIGOFF_INTERVAL; 1941 interval = BIGOFF_INTERVAL;
1918 } 1942 }
1919 1943
1920 set_next_and_ret:
1921 set_next(p, interval); 1944 set_next(p, interval);
1922} 1945}
1923 1946
@@ -2252,6 +2275,9 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
2252 /* Timed out waiting for reply */ 2275 /* Timed out waiting for reply */
2253 close(p->p_fd); 2276 close(p->p_fd);
2254 p->p_fd = -1; 2277 p->p_fd = -1;
2278 /* If poll interval is small, increase it */
2279 if (G.poll_exp < BIGPOLL)
2280 adjust_poll(MINPOLL);
2255 timeout = poll_interval(NOREPLY_INTERVAL); 2281 timeout = poll_interval(NOREPLY_INTERVAL);
2256 bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us", 2282 bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us",
2257 p->p_dotted, p->reachable_bits, timeout); 2283 p->p_dotted, p->reachable_bits, timeout);