blob: 83cb12d135b9c2e6d868bae891e79999ad4a6751 [file] [log] [blame]
From 11bbce7be6c86fd177ee903216ba43b8adba5e1f Mon Sep 17 00:00:00 2001
From: Avery Pennarun <apenwarr@gmail.com>
Date: Tue, 11 Jun 2013 00:26:19 -0400
Subject: Use error_interval() instead of QUERYTIME_MAX for each query packet.
The original implementation would wait QUERYTIME_MAX for each ntp request to
expire before *then* starting to count error_interval() seconds until the
next request. This caused problems because the initial settime_timeout
could expire before even retrying a single time. That, in turn, was
problematic if the first IP address in a multi-IP-address DNS entry turned
out not to work; we'd give up trying to set the time before we even tried
all the servers.
Now the retries are much faster (but still use the backoff interval).
---
client.c | 12 ++++++------
ntp.c | 6 +++---
ntpd.h | 3 +--
3 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/client.c b/client.c
index da6aa43..c0acaa2 100644
--- a/client.c
+++ b/client.c
@@ -118,7 +118,7 @@ client_query(struct ntp_peer *p)
int tos = IPTOS_LOWDELAY;
if (p->addr == NULL && client_nextaddr(p) == -1) {
- set_next(p, error_interval());
+ set_next(p, error_interval(0));
return (0);
}
@@ -136,7 +136,7 @@ client_query(struct ntp_peer *p)
errno == EHOSTUNREACH) {
client_log_error(p, "connect", errno);
client_nextaddr(p);
- set_next(p, error_interval());
+ set_next(p, error_interval(0));
return (-1);
} else
fatal("client_query connect");
@@ -171,7 +171,7 @@ client_query(struct ntp_peer *p)
}
p->state = STATE_QUERY_SENT;
- set_deadline(p, QUERYTIME_MAX);
+ set_deadline(p, error_interval(0));
return (0);
}
@@ -191,7 +191,7 @@ client_dispatch(struct ntp_peer *p, u_int8_t settime)
errno == ENETUNREACH || errno == ENETDOWN ||
errno == ECONNREFUSED || errno == EADDRNOTAVAIL) {
client_log_error(p, "recvfrom", errno);
- set_next(p, error_interval());
+ set_next(p, error_interval(0));
return (0);
} else
fatal("recvfrom");
@@ -207,7 +207,7 @@ client_dispatch(struct ntp_peer *p, u_int8_t settime)
if ((msg.status & LI_ALARM) == LI_ALARM || msg.stratum == 0 ||
msg.stratum > NTP_MAXSTRATUM) {
- interval = error_interval();
+ interval = error_interval(0);
set_next(p, interval);
log_info("reply from %s: not synced, next query %ds",
log_sockaddr((struct sockaddr *)&p->addr->ss), interval);
@@ -236,7 +236,7 @@ client_dispatch(struct ntp_peer *p, u_int8_t settime)
p->reply[p->shift].offset = ((T2 - T1) + (T3 - T4)) / 2;
p->reply[p->shift].delay = (T4 - T1) - (T3 - T2);
if (p->reply[p->shift].delay < 0) {
- interval = error_interval();
+ interval = error_interval(0);
set_next(p, interval);
log_info("reply from %s: negative delay %f",
log_sockaddr((struct sockaddr *)&p->addr->ss),
diff --git a/ntp.c b/ntp.c
index 4c33f7e..d8d14df 100644
--- a/ntp.c
+++ b/ntp.c
@@ -219,7 +219,7 @@ ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf)
if (p->deadline > 0 && p->deadline < nextaction)
nextaction = p->deadline;
if (p->deadline > 0 && p->deadline <= time(NULL)) {
- timeout = error_interval();
+ timeout = error_interval(1);
log_debug("no reply from %s received in time, "
"next query %ds", log_sockaddr(
(struct sockaddr *)&p->addr->ss), timeout);
@@ -542,7 +542,7 @@ scale_interval(time_t requested)
}
time_t
-error_interval(void)
+error_interval(int step_incr)
{
static time_t step = 1;
time_t interval, maxival, r;
@@ -552,7 +552,7 @@ error_interval(void)
if (interval > maxival)
interval = maxival;
else
- step++;
+ step += step_incr;
r = arc4random() % (interval / 10 + 1);
log_info("retrying in %d", interval + r);
return (interval + r);
diff --git a/ntpd.h b/ntpd.h
index 3bda1ec..e97c254 100644
--- a/ntpd.h
+++ b/ntpd.h
@@ -54,7 +54,6 @@
#define QSCALE_OFF_MIN 0.05
#define QSCALE_OFF_MAX 0.50
-#define QUERYTIME_MAX 15 /* single query might take n secs max */
#define OFFSET_ARRAY_SIZE 8
#define SETTIME_MIN_OFFSET 10 /* min offset for settime at start */
#define SETTIME_TIMEOUT 15 /* max seconds to wait with -s */
@@ -251,7 +250,7 @@ int client_dispatch(struct ntp_peer *, u_int8_t);
void client_log_error(struct ntp_peer *, const char *, int);
void update_scale(double);
time_t scale_interval(time_t);
-time_t error_interval(void);
+time_t error_interval(int step_incr);
void set_next(struct ntp_peer *, time_t);
/* util.c */
--
1.7.9.dirty