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 <henn...@openbsd.org> * Copyright (c) 2004 Alexander Guy <alexander....@andern.org> @@ -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 <alexander....@andern.org> - * - * 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); -}