diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2004-10-04 11:12:59 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2004-10-04 11:12:59 +0000 |
commit | b06e24ba496f53b794db7e570e734c9e8f5a3ce5 (patch) | |
tree | 4a77401478bd7c6f9beb8aab233db3ad72d3d9d5 | |
parent | 6c49049aadfdf8a4aa7fff06bae252c38a65bc86 (diff) |
do not take the average offset from all peers when calculating the total
offset to correct the local clock, but use the median.
given a reasonable sized set of servers this makes us nearly immune against
outliers or flasetickers, without the need for a horribly complicated outliers
detection which does not yield to better results anyway.
test & ok otto
-rw-r--r-- | usr.sbin/ntpd/ntp.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/usr.sbin/ntpd/ntp.c b/usr.sbin/ntpd/ntp.c index 1f955e2b527..bbc4fd6c666 100644 --- a/usr.sbin/ntpd/ntp.c +++ b/usr.sbin/ntpd/ntp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp.c,v 1.33 2004/09/18 20:01:38 henning Exp $ */ +/* $OpenBSD: ntp.c,v 1.34 2004/10/04 11:12:58 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -43,6 +43,7 @@ void ntp_sighdlr(int); int ntp_dispatch_imsg(void); void peer_add(struct ntp_peer *); void peer_remove(struct ntp_peer *); +int offset_compare(const void *, const void *); void ntp_sighdlr(int sig) @@ -345,23 +346,38 @@ peer_remove(struct ntp_peer *p) void ntp_adjtime(void) { - struct ntp_peer *p; - double offset_median = 0; - int offset_cnt = 0; + struct ntp_peer *p; + int offset_cnt = 0, i = 0; + struct ntp_peer **peers; + double offset_median; TAILQ_FOREACH(p, &conf->ntp_peers, entry) { if (p->trustlevel < TRUSTLEVEL_BADPEER) continue; - if (!p->update.good) return; - - offset_median += p->update.offset; offset_cnt++; } + if ((peers = calloc(offset_cnt, sizeof(struct ntp_peer *))) == NULL) + fatal("calloc ntp_adjtime"); + + TAILQ_FOREACH(p, &conf->ntp_peers, entry) { + if (p->trustlevel < TRUSTLEVEL_BADPEER) + continue; + peers[i++] = p; + } + + qsort(peers, offset_cnt, sizeof(struct ntp_peer *), offset_compare); + if (offset_cnt > 0) { - offset_median /= offset_cnt; + if (offset_cnt > 1 && offset_cnt % 2 == 0) + offset_median = + (peers[offset_cnt / 2 - 1]->update.offset + + peers[offset_cnt / 2]->update.offset) / 2; + else + offset_median = peers[offset_cnt / 2]->update.offset; + imsg_compose(ibuf_main, IMSG_ADJTIME, 0, 0, &offset_median, sizeof(offset_median)); @@ -369,10 +385,29 @@ ntp_adjtime(void) conf->status.leap = LI_NOWARNING; /* XXX */ } + free(peers); + TAILQ_FOREACH(p, &conf->ntp_peers, entry) p->update.good = 0; } +int +offset_compare(const void *aa, const void *bb) +{ + const struct ntp_peer * const *a; + const struct ntp_peer * const *b; + + a = aa; + b = bb; + + if ((*a)->update.offset < (*b)->update.offset) + return (-1); + else if ((*a)->update.offset > (*b)->update.offset) + return (1); + else + return (0); +} + void ntp_settime(double offset) { |