re
we've found a real bug behind the buffer sizes.
dns resolver was not limiting the response (ip list)
to any maximum number which is even defined already
as MAX_SERVERS_DNS. thus check that now.
now we can get away w/ much smaller buffers and
correct (non-overflowing) behaviour (;
cu
On Fri, May 15, 2009 at 03:19:02PM +0000, Michael Shalayeff wrote:
> re
> first try out of the zoo shown that we need to keep MAX_IMSGSIZE
> at 8k for more dns addresses (:
> diff updated
> cu
>
> On Fri, May 15, 2009 at 02:58:36PM +0000, Michael Shalayeff wrote:
> > re
> > forgot to mention that while there touching structs
> > also rearrange fields for optimal alignment (save memory)
> > and shrink io buffers to a half K from 8k since we will
> > never have a valid packet larger than that.
> > cu
> >
> > On Fri, May 15, 2009 at 02:39:29PM +0000, Michael Shalayeff wrote:
> > > re
> > > using floating point for ntpd math is not a good idea.
> > > this comes from the fact that mixing small and large numbers
> > > in one fp expression leads to a huge loss of precision.
> > > besides the fact that there is no need to change representation
> > > from fixed point (ntp timestamps) to floating point and
> > > back all the time. plus to that using fpu in daemons is
> > > not polite and eats even more cpu time (:
> > >
> > > this diff converts internal math to fixed point (64bit)
> > > except for one place -- local clock frequency drift.
> > > this part is still broken as one can see by constantly
> > > flipping frequency adjucements in the logs since math
> > > currently used performs computation on very large
> > > numbers (products of time stamps) and very small
> > > ones (products of time offsets) and thus totally useless.
> > > i have figured a better way to follow frequency drift
> > > but that can be done in the next step.
> > >
> > > this has ran on both i386 and sparc64 for months now
> > > and only has shown massive improvement in precision
> > > (decrease of deviation). thus local clock offset still
> > > flips every few hours from positive to negative and back
> > > due to broken frequency adjucements.
> > >
> > > please read and try.
Index: Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/Makefile,v
retrieving revision 1.2
diff -u -p -r1.2 Makefile
--- Makefile 13 May 2009 18:10:04 -0000 1.2
+++ Makefile 15 May 2009 16:09:17 -0000
@@ -3,7 +3,7 @@
PROG= ntpd
SRCS= ntpd.c buffer.c log.c imsg.c ntp.c ntp_msg.c ntp_dns.c \
- parse.y config.c server.c client.c sensors.c util.c
+ parse.y config.c server.c client.c sensors.c
CFLAGS+= -Wall -I${.CURDIR}
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
Index: client.c
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/client.c,v
retrieving revision 1.4
diff -u -p -r1.4 client.c
--- client.c 15 May 2009 11:40:42 -0000 1.4
+++ client.c 15 May 2009 16:09:17 -0000
@@ -195,19 +195,21 @@ client_query(struct ntp_peer *p)
int
client_dispatch(struct ntp_peer *p, u_int8_t settime)
{
- struct ntp_msg msg;
- struct msghdr somsg;
- struct iovec iov[1];
- struct timeval tv1;
- char buf[NTP_MSGSIZE];
+ extern int debug; /* from log.c */
+ struct ntp_msg msg;
+ struct msghdr somsg;
+ struct iovec iov[1];
+ struct timeval tv1, tv2;
+ char buf[NTP_MSGSIZE];
union {
struct cmsghdr hdr;
char buf[CMSG_SPACE(sizeof tv1)];
} cmsgbuf;
- struct cmsghdr *cmsg;
- ssize_t size;
- double T1, T2, T3, T4;
- time_t interval;
+ int64_t T1, T2, T3, T4;
+ struct cmsghdr *cmsg;
+ struct ntp_offset *reply;
+ ssize_t size;
+ time_t interval;
somsg.msg_name = NULL;
somsg.msg_namelen = 0;
@@ -219,7 +221,7 @@ client_dispatch(struct ntp_peer *p, u_in
somsg.msg_controllen = sizeof cmsgbuf.buf;
somsg.msg_flags = 0;
- T4 = getoffset();
+ getoffset(&tv2);
if ((size = recvmsg(p->query->fd, &somsg, 0)) < 0) {
if (errno == EHOSTUNREACH || errno == EHOSTDOWN ||
errno == ENETUNREACH || errno == ENETDOWN ||
@@ -243,17 +245,20 @@ client_dispatch(struct ntp_peer *p, u_in
return (0);
}
+ T4 = 0;
for (cmsg = CMSG_FIRSTHDR(&somsg); cmsg != NULL;
cmsg = CMSG_NXTHDR(&somsg, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_TIMESTAMP) {
memcpy(&tv1, CMSG_DATA(cmsg), sizeof tv1);
- T4 += tv1.tv_sec + JAN_1970 + 1.0e-6 * tv1.tv_usec;
+ T4 = timeval2int64(&tv1);
+ T4 += (int64_t)JAN_1970 << 31;
+ T4 += timeval2int64(&tv2);
break;
}
}
- if (T4 < JAN_1970) {
+ if (T4 == 0) {
client_log_error(p, "recvmsg control format", EBADF);
set_next(p, error_interval());
return (0);
@@ -301,8 +306,8 @@ client_dispatch(struct ntp_peer *p, u_in
*/
T1 = p->query->xmttime;
- T2 = lfp_to_d(msg.rectime);
- T3 = lfp_to_d(msg.xmttime);
+ T2 = lfxt2int64(&msg.rectime);
+ T3 = lfxt2int64(&msg.xmttime);
/*
* XXX workaround: time_t / tv_sec must never wrap.
@@ -314,32 +319,51 @@ client_dispatch(struct ntp_peer *p, u_in
return (0);
}
- 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) {
+ if (T4 <= T1) {
interval = error_interval();
set_next(p, interval);
- log_info("reply from %s: negative delay %fs, "
+ log_info("local clock is not monotonic");
+ return (0);
+ }
+
+ reply = &p->reply[p->shift];
+
+ reply->offset = ((T2 - T1) + (T3 - T4)) / 2;
+ reply->delay = (T4 - T1) - (T3 - T2);
+ if (reply->delay < 0) {
+ char *s = "";
+ int64_t val = reply->delay;
+ if (val < 0) {
+ s = "-";
+ val = -val;
+ }
+ int642timeval(val, &tv2);
+ interval = error_interval();
+ set_next(p, interval);
+ log_info("reply from %s: negative delay %s%ld.%06lus "
"next query %ds",
log_sockaddr((struct sockaddr *)&p->addr->ss),
- p->reply[p->shift].delay, interval);
+ s, tv2.tv_sec, tv2.tv_usec, interval);
return (0);
}
- p->reply[p->shift].error = (T2 - T1) - (T3 - T4);
- p->reply[p->shift].rcvd = getmonotime();
- p->reply[p->shift].good = 1;
-
- p->reply[p->shift].status.leap = (msg.status & LIMASK);
- p->reply[p->shift].status.precision = msg.precision;
- p->reply[p->shift].status.rootdelay = sfp_to_d(msg.rootdelay);
- p->reply[p->shift].status.rootdispersion = sfp_to_d(msg.dispersion);
- p->reply[p->shift].status.refid = msg.refid;
- p->reply[p->shift].status.reftime = lfp_to_d(msg.reftime);
- p->reply[p->shift].status.poll = msg.ppoll;
- p->reply[p->shift].status.stratum = msg.stratum;
+
+ p->shift = (p->shift + 1) % OFFSET_ARRAY_SIZE;
+
+ reply->error = (T2 - T1) - (T3 - T4);
+ reply->rcvd = getmonotime();
+ reply->good = 1;
+
+ reply->status.leap = msg.status & LIMASK;
+ reply->status.precision = msg.precision;
+ reply->status.refid = ntohl(msg.refid);
+ reply->status.poll = msg.ppoll;
+ reply->status.stratum = msg.stratum;
+ reply->status.rootdelay = sfxt2int64(&msg.rootdelay);
+ reply->status.rootdispersion = sfxt2int64(&msg.dispersion);
+ reply->status.reftime = lfxt2int64(&msg.reftime);
if (p->addr->ss.ss_family == AF_INET) {
- p->reply[p->shift].status.send_refid =
+ reply->status.send_refid =
((struct sockaddr_in *)&p->addr->ss)->sin_addr.s_addr;
} else if (p->addr->ss.ss_family == AF_INET6) {
MD5_CTX context;
@@ -349,10 +373,10 @@ client_dispatch(struct ntp_peer *p, u_in
MD5Update(&context, ((struct sockaddr_in6 *)&p->addr->ss)->
sin6_addr.s6_addr, sizeof(struct in6_addr));
MD5Final(digest, &context);
- memcpy((char *)&p->reply[p->shift].status.send_refid, digest,
+ memcpy((char *)&reply->status.send_refid, digest,
sizeof(u_int32_t));
} else
- p->reply[p->shift].status.send_refid = msg.xmttime.fractionl;
+ reply->status.send_refid = msg.xmttime.fractionl;
if (p->trustlevel < TRUSTLEVEL_PATHETIC)
interval = scale_interval(INTERVAL_QUERY_PATHETIC);
@@ -373,16 +397,25 @@ client_dispatch(struct ntp_peer *p, u_in
p->trustlevel++;
}
- log_debug("reply from %s: offset %f delay %f, "
- "next query %ds", log_sockaddr((struct sockaddr *)&p->addr->ss),
- p->reply[p->shift].offset, p->reply[p->shift].delay, interval);
+ if (debug) {
+ char *s = "";
+ int64_t val = reply->offset;
+ if (val < 0) {
+ s = "-";
+ val = -val;
+ }
+ int642timeval(val, &tv1);
+ int642timeval(reply->delay, &tv2);
+ log_debug("reply from %s: "
+ "offset %s%ld.%06lus delay %ld.%06lus, next query %ds",
+ log_sockaddr((struct sockaddr *)&p->addr->ss),
+ s, tv1.tv_sec, tv1.tv_usec, tv2.tv_sec, tv2.tv_usec,
+ interval);
+ }
client_update(p);
if (settime)
- priv_settime(p->reply[p->shift].offset);
-
- if (++p->shift >= OFFSET_ARRAY_SIZE)
- p->shift = 0;
+ priv_settime(reply->offset);
return (0);
}
@@ -390,7 +423,8 @@ client_dispatch(struct ntp_peer *p, u_in
int
client_update(struct ntp_peer *p)
{
- int i, best = 0, good = 0;
+ struct ntp_offset *reply, *best, *last;
+ int good;
/*
* clock filter
@@ -399,28 +433,26 @@ client_update(struct ntp_peer *p)
* invalidate it and all older ones
*/
- for (i = 0; good == 0 && i < OFFSET_ARRAY_SIZE; i++)
- if (p->reply[i].good) {
- good++;
- best = i;
- }
-
- for (; i < OFFSET_ARRAY_SIZE; i++)
- if (p->reply[i].good) {
- good++;
- if (p->reply[i].delay < p->reply[best].delay)
- best = i;
- }
+ for (good = 0, best = NULL, reply = &p->reply[0],
+ last = &p->reply[OFFSET_ARRAY_SIZE]; reply < last; reply++) {
+ if (!reply->good)
+ continue;
+ good++;
+ if (!best)
+ best = reply;
+ if (reply->delay < best->delay)
+ best = reply;
+ }
- if (good < 8)
+ if (good < OFFSET_ARRAY_SIZE)
return (-1);
- memcpy(&p->update, &p->reply[best], sizeof(p->update));
- if (priv_adjtime() == 0) {
- for (i = 0; i < OFFSET_ARRAY_SIZE; i++)
- if (p->reply[i].rcvd <= p->reply[best].rcvd)
- p->reply[i].good = 0;
- }
+ memcpy(&p->update, best, sizeof(p->update));
+ if (priv_adjtime() == 0)
+ for (reply = &p->reply[0], last = &p->reply[OFFSET_ARRAY_SIZE];
+ reply < last; reply++)
+ if (reply->rcvd <= best->rcvd)
+ reply->good = 0;
return (0);
}
Index: ntp.c
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/ntp.c,v
retrieving revision 1.3
diff -u -p -r1.3 ntp.c
--- ntp.c 13 May 2009 18:10:04 -0000 1.3
+++ ntp.c 15 May 2009 16:09:17 -0000
@@ -1,4 +1,3 @@
-
/*
* Copyright (c) 2003, 2004 Henning Brauer <[email protected]>
* Copyright (c) 2004 Alexander Guy <[email protected]>
@@ -168,7 +167,7 @@ ntp_main(int pipe_prnt[2], struct ntpd_c
conf->freq.xx = 0.0;
conf->freq.xy = 0.0;
conf->freq.y = 0.0;
- conf->freq.overall_offset = 0.0;
+ conf->freq.overall_offset = 0;
conf->status.synced = 0;
clock_getres(CLOCK_REALTIME, &tp);
@@ -522,9 +521,10 @@ peer_remove(struct ntp_peer *p)
}
static void
-priv_adjfreq(double offset)
+priv_adjfreq(int64_t offset)
{
- double curtime, freq;
+ double curtime, freq, doff;
+ int64_t relfreq;
if (!conf->status.synced)
return;
@@ -535,12 +535,12 @@ priv_adjfreq(double offset)
return;
conf->freq.overall_offset += offset;
- offset = conf->freq.overall_offset;
curtime = gettime_corrected();
- conf->freq.xy += offset * curtime;
+ doff = conf->freq.overall_offset;
+ conf->freq.xy += doff * curtime;
conf->freq.x += curtime;
- conf->freq.y += offset;
+ conf->freq.y += doff;
conf->freq.xx += curtime * curtime;
if (conf->freq.samples % FREQUENCY_SAMPLES != 0)
@@ -556,13 +556,14 @@ priv_adjfreq(double offset)
else if (freq < -MAX_FREQUENCY_ADJUST)
freq = -MAX_FREQUENCY_ADJUST;
- imsg_compose(ibuf_main, IMSG_ADJFREQ, 0, 0, &freq, sizeof(freq));
+ relfreq = freq * 1e9 * (1LL << 32);
+ imsg_compose(ibuf_main, IMSG_ADJFREQ, 0, 0, &relfreq, sizeof(relfreq));
conf->freq.xy = 0.0;
conf->freq.x = 0.0;
conf->freq.y = 0.0;
conf->freq.xx = 0.0;
conf->freq.samples = 0;
- conf->freq.overall_offset = 0.0;
+ conf->freq.overall_offset = 0;
conf->freq.num++;
}
@@ -573,7 +574,7 @@ priv_adjtime(void)
struct ntp_sensor *s;
int offset_cnt = 0, i = 0, j;
struct ntp_offset **offsets;
- double offset_median;
+ int64_t offset_median;
TAILQ_FOREACH(p, &conf->ntp_peers, entry) {
if (p->trustlevel < TRUSTLEVEL_BADPEER)
@@ -626,8 +627,8 @@ priv_adjtime(void)
}
conf->status.leap = offsets[i]->status.leap;
- imsg_compose(ibuf_main, IMSG_ADJTIME, 0, 0,
- &offset_median, sizeof(offset_median));
+ imsg_compose(ibuf_main, IMSG_ADJTIME, 0, 0, &offset_median,
+ sizeof(offset_median));
priv_adjfreq(offset_median);
@@ -671,9 +672,12 @@ offset_compare(const void *aa, const voi
}
void
-priv_settime(double offset)
+priv_settime(int64_t offset)
{
- imsg_compose(ibuf_main, IMSG_SETTIME, 0, 0, &offset, sizeof(offset));
+ struct timeval tv;
+
+ int642timeval(offset, &tv);
+ imsg_compose(ibuf_main, IMSG_SETTIME, 0, 0, &tv, sizeof(tv));
conf->settime = 0;
}
@@ -687,19 +691,24 @@ priv_host_dns(char *name, u_int32_t peer
}
void
-update_scale(double offset)
+update_scale(int64_t offset)
{
- offset += getoffset();
- if (offset < 0)
- offset = -offset;
+ struct timeval tv;
+ int64_t qscale;
+
+ getoffset(&tv);
+ offset += timeval2int64(&tv);
- if (offset > QSCALE_OFF_MAX || !conf->status.synced ||
- conf->freq.num < 3)
+ qscale = int64init(QSCALE_OFF_MAX / 1000000, QSCALE_OFF_MAX % 1000000);
+ if (offset > qscale || !conf->status.synced || conf->freq.num < 3)
conf->scale = 1;
- else if (offset < QSCALE_OFF_MIN)
- conf->scale = QSCALE_OFF_MAX / QSCALE_OFF_MIN;
- else
- conf->scale = QSCALE_OFF_MAX / offset;
+ else {
+ conf->scale = qscale / offset; /* XXX */
+ qscale = int64init(QSCALE_OFF_MIN / 1000000,
+ QSCALE_OFF_MIN % 1000000);
+ if (offset < qscale)
+ conf->scale = QSCALE_OFF_MAX / QSCALE_OFF_MIN;
+ }
}
time_t
@@ -776,4 +785,41 @@ report_peers(int always)
log_warnx("bad sensor %s", s->device);
}
}
+}
+
+int64_t
+gettime_corrected()
+{
+ struct timeval tv;
+ getoffset(&tv);
+ return gettime() + timeval2int64(&tv);
+}
+
+void
+getoffset(struct timeval *tv)
+{
+ if (adjtime(NULL, tv) == -1)
+ memset(tv, 0, sizeof(*tv));
+}
+
+int64_t
+gettime()
+{
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) == -1)
+ fatal("gettimeofday");
+
+ return timeval2int64(&tv) + ((int64_t)JAN_1970 << 31);
+}
+
+time_t
+getmonotime(void)
+{
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
+ fatal("clock_gettime");
+
+ return (ts.tv_sec);
}
Index: ntp.h
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/ntp.h,v
retrieving revision 1.2
diff -u -p -r1.2 ntp.h
--- ntp.h 13 May 2009 18:10:04 -0000 1.2
+++ ntp.h 15 May 2009 16:09:17 -0000
@@ -43,11 +43,41 @@ struct l_fixedpt {
u_int32_t fractionl;
};
+ /* 2147 = 2^31 / 1000000 */
+#define timeval2int64(tv) \
+ (((int64_t)(tv)->tv_sec << 31) + (2147U * (tv)->tv_usec))
+
+#define int64init(s,u) (((int64_t)(s) << 31) + (2147U * (u)))
+
+#define int642timeval(i,tv) do { \
+ (tv)->tv_sec = (i) >> 31; \
+ (tv)->tv_usec = ((i) & 0x7fffffff) / 2148; \
+} while (0)
+
+#define lfxt2int64(lf) \
+ (((int64_t)ntohl((lf)->int_partl) << 31) + (ntohl((lf)->fractionl) >> 1))
+
+#define int642lfxt(i,lf) do { \
+ (lf)->int_partl = htonl((i) >> 31); \
+ (lf)->fractionl = htonl((i) << 1); \
+} while (0)
+
+#define us2int64(us) (2147ULL * (us))
+
struct s_fixedpt {
u_int16_t int_parts;
u_int16_t fractions;
};
+#define int642sfxt(i,lf) do { \
+ (lf)->int_parts = htons((i) >> 31); \
+ (lf)->fractions = htons((i & 0x7fffffff) >> 15); \
+} while (0)
+
+#define sfxt2int64(lf) \
+ (((int64_t)ntohs((lf)->int_parts) << 31) + \
+ ((u_int)ntohs((lf)->fractions) << 15))
+
/* RFC Section 4
*
* 0 1 2 3
@@ -107,9 +137,9 @@ struct ntp_msg {
} __packed;
struct ntp_query {
- int fd;
- struct ntp_msg msg;
- double xmttime;
+ struct ntp_msg msg;
+ int64_t xmttime;
+ int fd;
};
/*
@@ -139,8 +169,8 @@ struct ntp_query {
#define MODE_RES1 6 /* reserved for NTP control message */
#define MODE_RES2 7 /* reserved for private use */
-#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
-#define JAN_2030 1893456000UL + JAN_1970 /* 1. 1. 2030 00:00:00
*/
+#define JAN_1970 2208988800LL /* 1970 - 1900 in seconds */
+#define JAN_2030 ((JAN_1970 + 1893456000LL) << 31) /* 1. 1. 2030
00:00:00 */
#define NTP_VERSION 4
#define NTP_MAXSTRATUM 15
Index: ntp_dns.c
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/ntp_dns.c,v
retrieving revision 1.2
diff -u -p -r1.2 ntp_dns.c
--- ntp_dns.c 14 May 2009 12:23:33 -0000 1.2
+++ ntp_dns.c 15 May 2009 16:09:17 -0000
@@ -147,14 +147,15 @@ dns_dispatch_imsg(void)
fatalx("invalid IMSG_HOST_DNS received");
if ((cnt = host_dns(name, &hn, conf)) == -1)
break;
+ if (cnt > MAX_SERVERS_DNS)
+ cnt = MAX_SERVERS_DNS;
buf = imsg_create(ibuf_dns, IMSG_HOST_DNS,
imsg.hdr.peerid, 0,
cnt * sizeof(struct sockaddr_storage));
if (buf == NULL)
break;
- if (cnt > 0)
- for (h = hn; h != NULL; h = h->next)
- imsg_add(buf, &h->ss, sizeof(h->ss));
+ for (h = hn; cnt-- && h != NULL; h = h->next)
+ imsg_add(buf, &h->ss, sizeof(h->ss));
imsg_close(ibuf_dns, buf);
break;
Index: ntpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/ntpd.c,v
retrieving revision 1.4
diff -u -p -r1.4 ntpd.c
--- ntpd.c 14 May 2009 12:23:33 -0000 1.4
+++ ntpd.c 15 May 2009 16:09:17 -0000
@@ -38,11 +38,11 @@ int main(int, char *[]);
int check_child(pid_t, const char *);
int dispatch_imsg(struct ntpd_conf *);
void reset_adjtime(void);
-int ntpd_adjtime(double);
-void ntpd_adjfreq(double, int);
-void ntpd_settime(double);
+int ntpd_adjtime(int64_t);
+void ntpd_adjfreq(int64_t, int);
+void ntpd_settime(struct timeval *);
void readfreq(void);
-int writefreq(double);
+int writefreq(int64_t);
volatile sig_atomic_t quit = 0;
volatile sig_atomic_t reconfig = 0;
@@ -271,10 +271,11 @@ dispatch_imsg(struct ntpd_conf *lconf)
{
struct imsg imsg;
int n, cnt;
- double d;
+ struct timeval tv;
char *name;
struct ntp_addr *h, *hn;
struct buf *buf;
+ int64_t d;
if ((n = imsg_read(ibuf)) == -1)
return (-1);
@@ -306,13 +307,13 @@ dispatch_imsg(struct ntpd_conf *lconf)
ntpd_adjfreq(d, 1);
break;
case IMSG_SETTIME:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d))
+ if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(tv))
fatalx("invalid IMSG_SETTIME received");
if (!lconf->settime)
break;
log_init(lconf->debug);
- memcpy(&d, imsg.data, sizeof(d));
- ntpd_settime(d);
+ memcpy(&tv, imsg.data, sizeof(tv));
+ ntpd_settime(&tv);
/* daemonize now */
if (!lconf->debug)
if (daemon(1, 0))
@@ -361,19 +362,30 @@ reset_adjtime(void)
}
int
-ntpd_adjtime(double d)
+ntpd_adjtime(int64_t d)
{
- struct timeval tv, olddelta;
- int synced = 0;
static int firstadj = 1;
+ struct timeval tv, tv1, olddelta;
+ char *s = "";
+ int synced = 0;
- d += getoffset();
- if (d >= (double)LOG_NEGLIGIBLE_ADJTIME / 1000 ||
- d <= -1 * (double)LOG_NEGLIGIBLE_ADJTIME / 1000)
- log_info("adjusting local clock by %fs", d);
+ getoffset(&olddelta);
+ int642timeval(d, &tv);
+ timeradd(&tv, &olddelta, &tv);
+
+ if (d < 0) {
+ s = "-";
+ d = -d;
+ }
+
+ int642timeval(d, &tv1);
+ if (tv1.tv_sec || tv1.tv_usec >= LOG_NEGLIGEE * 1000)
+ log_info("adjusting local clock by %s%ld.%06lus",
+ s, tv1.tv_sec, tv1.tv_usec);
else
- log_debug("adjusting local clock by %fs", d);
- d_to_tv(d, &tv);
+ log_debug("adjusting local clock by %s%ld.%06lus",
+ s, tv1.tv_sec, tv1.tv_usec);
+
if (adjtime(&tv, &olddelta) == -1)
log_warn("adjtime failed");
else if (!firstadj && olddelta.tv_sec == 0 && olddelta.tv_usec == 0)
@@ -383,44 +395,42 @@ ntpd_adjtime(double d)
}
void
-ntpd_adjfreq(double relfreq, int wrlog)
+ntpd_adjfreq(int64_t relfreq, int wrlog)
{
int64_t curfreq;
- double ppmfreq;
+ char *sign = "";
int r;
if (adjfreq(NULL, &curfreq) == -1) {
log_warn("adjfreq failed");
return;
}
+ curfreq += relfreq;
/*
- * adjfreq's unit is ns/s shifted left 32; convert relfreq to
- * that unit before adding. We log values in part per million.
+ * adjfreq's unit is ns/s shifted left 32.
+ * We log values in part per million.
*/
- curfreq += relfreq * 1e9 * (1LL << 32);
- r = writefreq(curfreq / 1e9 / (1LL << 32));
- ppmfreq = relfreq * 1e6;
- if (wrlog) {
- if (ppmfreq >= LOG_NEGLIGIBLE_ADJFREQ ||
- ppmfreq <= -LOG_NEGLIGIBLE_ADJFREQ)
- log_info("adjusting clock frequency by %f to %fppm%s",
- ppmfreq, curfreq / 1e3 / (1LL << 32),
- r ? "" : " (no drift file)");
- else
- log_debug("adjusting clock frequency by %f to %fppm%s",
- ppmfreq, curfreq / 1e3 / (1LL << 32),
- r ? "" : " (no drift file)");
- }
+ r = writefreq(curfreq);
+ if (relfreq < 0) {
+ relfreq = -relfreq;
+ sign = "-";
+ }
+ if (wrlog)
+ log_info("adjusting clock frequency by %s0.%06d to
%d.%06dppm%s",
+ sign, (int)(relfreq >> 32) % 1000000,
+ (int)(curfreq >> 32) / 1000000,
+ (int)(curfreq >> 32) % 1000000,
+ r ? " (no drift file)" : "");
if (adjfreq(&curfreq, NULL) == -1)
log_warn("adjfreq failed");
}
void
-ntpd_settime(double d)
+ntpd_settime(struct timeval *tv)
{
- struct timeval tv, curtime;
+ struct timeval curtime;
char buf[80];
time_t tval;
@@ -428,9 +438,8 @@ ntpd_settime(double d)
log_warn("gettimeofday");
return;
}
- d_to_tv(d, &tv);
- curtime.tv_usec += tv.tv_usec + 1000000;
- curtime.tv_sec += tv.tv_sec - 1 + (curtime.tv_usec / 1000000);
+ curtime.tv_usec += tv->tv_usec + 1000000;
+ curtime.tv_sec += tv->tv_sec - 1 + (curtime.tv_usec / 1000000);
curtime.tv_usec %= 1000000;
if (settimeofday(&curtime, NULL) == -1) {
@@ -440,15 +449,15 @@ ntpd_settime(double d)
tval = curtime.tv_sec;
strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y",
localtime(&tval));
- log_info("set local clock to %s (offset %fs)", buf, d);
+ log_info("set local clock to %s (offset %ld.%06lus)", buf,
+ tv->tv_sec, tv->tv_usec);
}
void
readfreq(void)
{
+ int64_t current, d;
FILE *fp;
- int64_t current;
- double d;
fp = fopen(DRIFTFILE, "r");
if (fp == NULL) {
@@ -463,7 +472,7 @@ readfreq(void)
if (adjfreq(NULL, ¤t) == -1)
log_warn("adjfreq failed");
else if (current == 0) {
- if (fscanf(fp, "%le", &d) == 1)
+ if (fscanf(fp, "%lld", &d) == 1)
ntpd_adjfreq(d, 0);
else
log_warnx("can't read %s", DRIFTFILE);
@@ -472,7 +481,7 @@ readfreq(void)
}
int
-writefreq(double d)
+writefreq(int64_t d)
{
int r;
FILE *fp;
@@ -484,10 +493,10 @@ writefreq(double d)
log_warn("can't open %s", DRIFTFILE);
warnonce = 0;
}
- return 0;
+ return -1;
}
- fprintf(fp, "%e\n", d);
+ fprintf(fp, "%lld\n", d);
r = ferror(fp);
if (fclose(fp) != 0 || r != 0) {
if (warnonce) {
@@ -495,7 +504,7 @@ writefreq(double d)
warnonce = 0;
}
unlink(DRIFTFILE);
- return 0;
+ return -1;
}
- return 1;
+ return 0;
}
Index: ntpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/ntpd.h,v
retrieving revision 1.4
diff -u -p -r1.4 ntpd.h
--- ntpd.h 14 May 2009 12:23:33 -0000 1.4
+++ ntpd.h 15 May 2009 16:09:17 -0000
@@ -34,7 +34,7 @@
#define CONFFILE "/etc/ntpd.conf"
#define DRIFTFILE "/var/db/ntpd.drift"
-#define READ_BUF_SIZE 8192
+#define READ_BUF_SIZE (256 * 10)
#define INTERVAL_QUERY_NORMAL 30 /* sync to peers every
n secs */
#define INTERVAL_QUERY_PATHETIC 60
@@ -47,15 +47,14 @@
#define MAX_SERVERS_DNS 8
-#define QSCALE_OFF_MIN 0.001
-#define QSCALE_OFF_MAX 0.050
+#define QSCALE_OFF_MIN 50000 /* us */
+#define QSCALE_OFF_MAX 500000 /* us */
#define QUERYTIME_MAX 15 /* single query might take n
secs max */
#define OFFSET_ARRAY_SIZE 8
#define SENSOR_OFFSETS 7
#define SETTIME_TIMEOUT 15 /* max seconds to wait with -s
*/
-#define LOG_NEGLIGIBLE_ADJTIME 32 /* negligible drift to not log
(ms) */
-#define LOG_NEGLIGIBLE_ADJFREQ 0.05 /* negligible rate to not log
(ppm) */
+#define LOG_NEGLIGEE 32 /* negligible drift to not log
(ms) */
#define FREQUENCY_SAMPLES 8 /* samples for est. of
permanent drift */
#define MAX_FREQUENCY_ADJUST 128e-5 /* max correction per iteration
*/
#define REPORT_INTERVAL (24*60*60) /* interval between status
reports */
@@ -94,9 +93,9 @@ struct ntp_addr_wrap {
};
struct ntp_status {
- double rootdelay;
- double rootdispersion;
- double reftime;
+ int64_t rootdelay;
+ int64_t rootdispersion;
+ int64_t reftime;
u_int32_t refid;
u_int32_t send_refid;
u_int8_t synced;
@@ -108,9 +107,9 @@ struct ntp_status {
struct ntp_offset {
struct ntp_status status;
- double offset;
- double delay;
- double error;
+ int64_t offset;
+ int64_t delay;
+ int64_t error;
time_t rcvd;
u_int8_t good;
};
@@ -126,56 +125,56 @@ struct ntp_peer {
time_t next;
time_t deadline;
u_int32_t id;
+ int lasterror;
+ int senderrors;
u_int8_t shift;
u_int8_t trustlevel;
u_int8_t weight;
- int lasterror;
- int senderrors;
};
struct ntp_sensor {
TAILQ_ENTRY(ntp_sensor) entry;
struct ntp_offset offsets[SENSOR_OFFSETS];
struct ntp_offset update;
+ int64_t correction;
time_t next;
time_t last;
char *device;
u_int32_t refid;
int sensordevid;
- int correction;
u_int8_t weight;
u_int8_t shift;
};
struct ntp_conf_sensor {
- TAILQ_ENTRY(ntp_conf_sensor) entry;
- char *device;
- char *refstr;
- int correction;
- u_int8_t weight;
+ TAILQ_ENTRY(ntp_conf_sensor) entry;
+ char *device;
+ char *refstr;
+ int correction;
+ u_int8_t weight;
};
struct ntp_freq {
- double overall_offset;
- double x, y;
- double xx, xy;
- int samples;
- u_int num;
+ double x, y;
+ double xx, xy;
+ int64_t overall_offset;
+ int samples;
+ u_int num;
};
struct ntpd_conf {
- TAILQ_HEAD(listen_addrs, listen_addr) listen_addrs;
- TAILQ_HEAD(ntp_peers, ntp_peer) ntp_peers;
- TAILQ_HEAD(ntp_sensors, ntp_sensor) ntp_sensors;
- TAILQ_HEAD(ntp_conf_sensors, ntp_conf_sensor) ntp_conf_sensors;
- struct ntp_status status;
- struct ntp_freq freq;
- u_int8_t listen_all;
- u_int8_t settime;
- u_int8_t debug;
- u_int32_t scale;
- u_int8_t noaction;
- u_int8_t family;
+ TAILQ_HEAD(, listen_addr) listen_addrs;
+ TAILQ_HEAD(, ntp_peer) ntp_peers;
+ TAILQ_HEAD(, ntp_sensor) ntp_sensors;
+ TAILQ_HEAD(, ntp_conf_sensor) ntp_conf_sensors;
+ struct ntp_status status;
+ struct ntp_freq freq;
+ u_int32_t scale;
+ u_int8_t listen_all;
+ u_int8_t settime;
+ u_int8_t debug;
+ u_int8_t noaction;
+ u_int8_t family;
};
struct buf {
@@ -201,7 +200,7 @@ struct buf_read {
/* ipc messages */
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
-#define MAX_IMSGSIZE 8192
+#define MAX_IMSGSIZE (256 * 10)
struct imsgbuf {
int fd;
@@ -264,14 +263,18 @@ int imsg_close(struct imsgbuf *, struct
void imsg_free(struct imsg *);
/* ntp.c */
-pid_t ntp_main(int[2], struct ntpd_conf *, struct passwd *);
-int priv_adjtime(void);
-void priv_settime(double);
-void priv_host_dns(char *, u_int32_t);
-int offset_compare(const void *, const void *);
-void update_scale(double);
-time_t scale_interval(time_t);
-time_t error_interval(void);
+pid_t ntp_main(int[2], struct ntpd_conf *, struct passwd *);
+int priv_adjtime(void);
+void priv_settime(int64_t);
+void priv_host_dns(char *, u_int32_t);
+int offset_compare(const void *, const void *);
+void update_scale(int64_t);
+time_t scale_interval(time_t);
+time_t error_interval(void);
+int64_t gettime_corrected(void);
+void getoffset(struct timeval *);
+int64_t gettime(void);
+time_t getmonotime(void);
extern struct ntpd_conf *conf;
/* parse.y */
@@ -301,23 +304,12 @@ int client_dispatch(struct ntp_peer *, u
void client_log_error(struct ntp_peer *, const char *, int);
void set_next(struct ntp_peer *, time_t);
-/* util.c */
-double gettime_corrected(void);
-double getoffset(void);
-double gettime(void);
-time_t getmonotime(void);
-void d_to_tv(double, struct timeval *);
-double lfp_to_d(struct l_fixedpt);
-struct l_fixedpt d_to_lfp(double);
-double sfp_to_d(struct s_fixedpt);
-struct s_fixedpt d_to_sfp(double);
-
/* sensors.c */
-void sensor_init(void);
-int sensor_scan(void);
-void sensor_query(struct ntp_sensor *);
-int sensor_hotplugfd(void);
-void sensor_hotplugevent(int);
+void sensor_init(void);
+int sensor_scan(void);
+void sensor_query(struct ntp_sensor *);
+int sensor_hotplugfd(void);
+void sensor_hotplugevent(int);
/* ntp_dns.c */
pid_t ntp_dns(int[2], struct ntpd_conf *, struct passwd *);
Index: sensors.c
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/sensors.c,v
retrieving revision 1.3
diff -u -p -r1.3 sensors.c
--- sensors.c 13 May 2009 18:10:04 -0000 1.3
+++ sensors.c 15 May 2009 16:09:18 -0000
@@ -121,7 +121,7 @@ sensor_add(int sensordev, char *dxname)
s->next = getmonotime();
s->weight = cs->weight;
- s->correction = cs->correction;
+ s->correction = us2int64(cs->correction);
if ((s->device = strdup(dxname)) == NULL)
fatal("sensor_add strdup");
s->sensordevid = sensordev;
@@ -135,8 +135,10 @@ sensor_add(int sensordev, char *dxname)
TAILQ_INSERT_TAIL(&conf->ntp_sensors, s, entry);
- log_debug("sensor %s added (weight %d, correction %.6f, refstr %.4s)",
- s->device, s->weight, s->correction / 1e6, &s->refid);
+ log_debug(
+ "sensor %s added (weight %d, correction %d.%06u, refstr %-4s)",
+ s->device, s->weight,
+ cs->correction / 1000000, cs->correction % 1000000, &s->refid);
}
void
@@ -152,6 +154,7 @@ sensor_query(struct ntp_sensor *s)
{
char dxname[MAXDEVNAMLEN];
struct sensor sensor;
+ struct timeval tv;
if (conf->settime)
s->next = getmonotime() + SENSOR_QUERY_INTERVAL_SETTIME;
@@ -186,16 +189,17 @@ sensor_query(struct ntp_sensor *s)
* sensor.value = TS - TD in ns
* if value is positive, system time is ahead
*/
- s->offsets[s->shift].offset = (sensor.value / -1e9) - getoffset() +
- (s->correction / 1e6);
+ getoffset(&tv);
+ s->offsets[s->shift].offset = s->correction +
+ us2int64(sensor.value / 1000) - timeval2int64(&tv);
s->offsets[s->shift].rcvd = sensor.tv.tv_sec;
s->offsets[s->shift].good = 1;
s->offsets[s->shift].status.send_refid = s->refid;
- s->offsets[s->shift].status.stratum = 0; /* increased when sent
out */
+ s->offsets[s->shift].status.stratum = 0; /* increased when sent out */
s->offsets[s->shift].status.rootdelay = 0;
s->offsets[s->shift].status.rootdispersion = 0;
- s->offsets[s->shift].status.reftime = sensor.tv.tv_sec;
+ s->offsets[s->shift].status.reftime = timeval2int64(&sensor.tv);
s->offsets[s->shift].status.synced = 1;
log_debug("sensor %s: offset %f", s->device,
@@ -226,10 +230,9 @@ sensor_update(struct ntp_sensor *s)
i = SENSOR_OFFSETS / 2;
memcpy(&s->update, offsets[i], sizeof(s->update));
- if (SENSOR_OFFSETS % 2 == 0) {
+ if (SENSOR_OFFSETS % 2 == 0)
s->update.offset =
(offsets[i - 1]->offset + offsets[i]->offset) / 2;
- }
free(offsets);
log_debug("sensor update %s: offset %f", s->device, s->update.offset);
Index: server.c
===================================================================
RCS file: /cvs/src/usr.sbin/ntpd/server.c,v
retrieving revision 1.3
diff -u -p -r1.3 server.c
--- server.c 13 May 2009 18:10:04 -0000 1.3
+++ server.c 15 May 2009 16:09:18 -0000
@@ -127,11 +127,11 @@ server_dispatch(int fd, struct ntpd_conf
{
ssize_t size;
u_int8_t version;
- double rectime;
struct sockaddr_storage fsa;
socklen_t fsa_len;
struct ntp_msg query, reply;
char buf[NTP_MSGSIZE];
+ int64_t rectime;
fsa_len = sizeof(fsa);
if ((size = recvfrom(fd, &buf, sizeof(buf), 0,
@@ -146,7 +146,6 @@ server_dispatch(int fd, struct ntpd_conf
}
rectime = gettime_corrected();
-
if (ntp_getmsg((struct sockaddr *)&fsa, buf, size, &query) == -1)
return (0);
@@ -163,15 +162,16 @@ server_dispatch(int fd, struct ntpd_conf
else
reply.status |= MODE_SYM_PAS;
+ reply.refid = lconf->status.refid;
reply.stratum = lconf->status.stratum;
reply.ppoll = query.ppoll;
reply.precision = lconf->status.precision;
- reply.rectime = d_to_lfp(rectime);
- reply.reftime = d_to_lfp(lconf->status.reftime);
- reply.xmttime = d_to_lfp(gettime_corrected());
reply.orgtime = query.xmttime;
- reply.rootdelay = d_to_sfp(lconf->status.rootdelay);
- reply.refid = lconf->status.refid;
+ int642lfxt(rectime, &reply.rectime);
+ int642lfxt(lconf->status.reftime, &reply.reftime);
+ int642sfxt(lconf->status.rootdelay, &reply.rootdelay);
+ rectime = gettime_corrected();
+ int642lfxt(rectime, &reply.xmttime);
ntp_sendmsg(fd, (struct sockaddr *)&fsa, &reply, size, 0);
return (0);
Index: util.c
===================================================================
RCS file: util.c
diff -N util.c
--- util.c 26 Aug 2008 14:44:25 -0000 1.1.1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,118 +0,0 @@
-
-/*
- * Copyright (c) 2004 Alexander Guy <[email protected]>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/time.h>
-#include <limits.h>
-
-#include "ntpd.h"
-
-double
-gettime_corrected(void)
-{
- return (gettime() + getoffset());
-}
-
-double
-getoffset(void)
-{
- struct timeval tv;
- if (adjtime(NULL, &tv) == -1)
- return (0.0);
- return (tv.tv_sec + 1.0e-6 * tv.tv_usec);
-}
-
-double
-gettime(void)
-{
- struct timeval tv;
-
- if (gettimeofday(&tv, NULL) == -1)
- fatal("gettimeofday");
-
- return (tv.tv_sec + JAN_1970 + 1.0e-6 * tv.tv_usec);
-}
-
-time_t
-getmonotime(void)
-{
- struct timespec ts;
-
- if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
- fatal("clock_gettime");
-
- return (ts.tv_sec);
-}
-
-
-void
-d_to_tv(double d, struct timeval *tv)
-{
- tv->tv_sec = (long)d;
- tv->tv_usec = (d - tv->tv_sec) * 1000000;
- while (tv->tv_usec < 0) {
- tv->tv_usec += 1000000;
- tv->tv_sec -= 1;
- }
-}
-
-double
-lfp_to_d(struct l_fixedpt lfp)
-{
- double ret;
-
- lfp.int_partl = ntohl(lfp.int_partl);
- lfp.fractionl = ntohl(lfp.fractionl);
-
- ret = (double)(lfp.int_partl) + ((double)lfp.fractionl / UINT_MAX);
-
- return (ret);
-}
-
-struct l_fixedpt
-d_to_lfp(double d)
-{
- struct l_fixedpt lfp;
-
- lfp.int_partl = htonl((u_int32_t)d);
- lfp.fractionl = htonl((u_int32_t)((d - (u_int32_t)d) * UINT_MAX));
-
- return (lfp);
-}
-
-double
-sfp_to_d(struct s_fixedpt sfp)
-{
- double ret;
-
- sfp.int_parts = ntohs(sfp.int_parts);
- sfp.fractions = ntohs(sfp.fractions);
-
- ret = (double)(sfp.int_parts) + ((double)sfp.fractions / USHRT_MAX);
-
- return (ret);
-}
-
-struct s_fixedpt
-d_to_sfp(double d)
-{
- struct s_fixedpt sfp;
-
- sfp.int_parts = htons((u_int16_t)d);
- sfp.fractions = htons((u_int16_t)((d - (u_int16_t)d) * USHRT_MAX));
-
- return (sfp);
-}