From ed7b4737c85d1079def2e3977e282f1cf835dff3 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 26 Jun 2007 02:40:20 +0000 Subject: [PATCH] Add a new option (-i) that allows the insane deviation value to be set, and change the default to 0.5 seconds. For example, -i 0.025 would set the test to be 25ms. Change the insane check... just map out a server deemed to be insane for 60 minutes, do not disconnect or reset it (which might lead to excessive packet traffic). Update the documentation. --- usr.sbin/dntpd/client.c | 57 +++++++++++++++++++++++++++++-------------------- usr.sbin/dntpd/defs.h | 3 ++- usr.sbin/dntpd/dntpd.8 | 31 ++++++++++++++++++++++++++- usr.sbin/dntpd/main.c | 8 +++++-- 4 files changed, 72 insertions(+), 27 deletions(-) diff --git a/usr.sbin/dntpd/client.c b/usr.sbin/dntpd/client.c index 19880627d5..5912689dc2 100644 --- a/usr.sbin/dntpd/client.c +++ b/usr.sbin/dntpd/client.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/usr.sbin/dntpd/client.c,v 1.12 2007/06/26 00:40:35 dillon Exp $ + * $DragonFly: src/usr.sbin/dntpd/client.c,v 1.13 2007/06/26 02:40:20 dillon Exp $ */ #include "defs.h" @@ -103,30 +103,22 @@ client_main(struct server_info **info_ary, int count) * best_off meets the quorum requirements and is good * (keep best_off) */ + best_off->server_insane = 0; } else if (insane == 0) { /* * best_off is probably good, but we do not have enough * servers reporting yet to meet the quorum requirements. */ best_off = NULL; - } else if (best_off->server_insane == 0) { - /* - * This server is insane, mark it (first report) - */ - best_off->server_insane = 1; - client_setserverstate(best_off, 0, - "FAILED - server reports insane offset, reconnecting"); - disconnect_server(best_off); - best_off->poll_mode = POLL_FIXED; - best_off->poll_count = 0; - lin_reset(best_off); } else { /* - * This server is still insane, permanently disable it. + * best_off is ugly, mark the server as being insane for + * 60 minutes. */ - disconnect_server(best_off); - client_setserverstate(best_off, -2, - "FAILED - permanently disabling insane server"); + best_off->server_insane = 60 * 60; + logdebuginfo(best_off, 1, + "excessive offset deviation, mapping out\n"); + best_off = NULL; } } @@ -188,6 +180,14 @@ client_poll(server_info_t info, int poll_interval, int calc_offset_correction) double offset; /* + * Adjust the insane-server countdown + */ + if (info->server_insane > poll_interval) + info->server_insane -= poll_interval; + else + info->server_insane = 0; + + /* * By default we always poll. If the polling interval comes under * active management the poll_sleep will be non-zero. */ @@ -328,10 +328,15 @@ client_check(struct server_info **checkp, * Use the standard-deviation and require at least 4 samples. An * offset correction is valid if the standard deviation is less then * the average offset divided by 4. + * + * Servers marked as being insane are not allowed */ info = *best_off; if (check->lin_countoffset >= 4 && - check->lin_cache_stddev < fabs(check->lin_sumoffset / check->lin_countoffset / 4)) { + (check->lin_cache_stddev < + fabs(check->lin_sumoffset / check->lin_countoffset / 4)) && + check->server_insane == 0 + ) { if (info == NULL || fabs(check->lin_cache_stddev) < fabs(info->lin_cache_stddev) ) { @@ -596,7 +601,7 @@ client_check_duplicate_ips(struct server_info **info_ary, int count) * off. If we have at least three servers in the pool require that a * quorum agree that the current best server's offset is reasonable. * - * Allow +/- 30 seconds of error for now. + * Allow +/- 0.5 seconds of error for now (settable with option). * * Returns -1 if insane, 0 if not enough samples, and 1 if ok */ @@ -643,17 +648,22 @@ client_insane(struct server_info **info_ary, int count, server_info_t best) skip = 0; /* - * Find the good, the bad, and the ugly. + * Find the good, the bad, and the ugly. We need at least four samples + * and a stddev within the deviation being checked to count a server + * in the calculation. */ for (i = 0; i < count; ++i) { info = info_ary[i]; - if (info->lin_countoffset < 2) { + if (info->lin_countoffset < 4 || + info->lin_cache_stddev > insane_deviation + ) { ++skip; continue; } + info_offset = info->lin_sumoffset / info->lin_countoffset; info_offset -= best_offset; - if (info_offset < -30.0 || info_offset > 30.0) + if (info_offset < -insane_deviation || info_offset > insane_deviation) ++bad; else ++good; @@ -662,8 +672,9 @@ client_insane(struct server_info **info_ary, int count, server_info_t best) /* * Did we meet our quorum? */ - logdebuginfo(best, 5, "insanecheck good=%d bad=%d skip=%d quorum=%d\n", - good, bad, skip, quorum); + logdebuginfo(best, 5, "insanecheck good=%d bad=%d skip=%d " + "quorum=%d (allowed=%-+8.6f)\n", + good, bad, skip, quorum, insane_deviation); if (good >= quorum) return(1); if (good + skip >= quorum) diff --git a/usr.sbin/dntpd/defs.h b/usr.sbin/dntpd/defs.h index e859712965..18d6856a5e 100644 --- a/usr.sbin/dntpd/defs.h +++ b/usr.sbin/dntpd/defs.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/usr.sbin/dntpd/defs.h,v 1.10 2007/06/25 21:33:36 dillon Exp $ + * $DragonFly: src/usr.sbin/dntpd/defs.h,v 1.11 2007/06/26 02:40:20 dillon Exp $ */ #include @@ -73,6 +73,7 @@ extern int min_sleep_opt; extern int nom_sleep_opt; extern int max_sleep_opt; extern int log_stderr; +extern double insane_deviation; int udp_socket(const char *target, int port, struct sockaddr_in *sam); int udp_ntptimereq(int fd, struct timeval *rtvp, diff --git a/usr.sbin/dntpd/dntpd.8 b/usr.sbin/dntpd/dntpd.8 index 53bd946dd7..6928d322fb 100644 --- a/usr.sbin/dntpd/dntpd.8 +++ b/usr.sbin/dntpd/dntpd.8 @@ -1,4 +1,4 @@ -.\" $DragonFly: src/usr.sbin/dntpd/dntpd.8,v 1.12 2007/05/17 08:19:03 swildner Exp $ +.\" $DragonFly: src/usr.sbin/dntpd/dntpd.8,v 1.13 2007/06/26 02:40:20 dillon Exp $ .\" .\" Copyright (c) 2005 The DragonFly Project. All rights reserved. .\" @@ -43,6 +43,7 @@ .Bk -words .Op Fl dnqstFSQ .Op Fl f Ar config_file +.Op Fl i Ar insane_deviation .Op Fl l Ar log_level .Op Fl T Ar nominal_poll .Op Fl L Ar maximum_poll @@ -118,6 +119,14 @@ Terminate any running background daemon and exit. .It Fl f Ar config_file Specify the configuration file. The default is .Pa /etc/dntpd.conf . +.It Fl i Ar insane_deviation +Specify how much deviation is allowed in calculated offsets, in seconds. +Fractions may be specified. +A quorum of servers must agree with the one we select as being the best time +source in order for us to select that source. +The default deviation allowed is a fairly expansive 0.5 seconds. +Note that offset errors due to internet packet latency can +exceed 25ms (0.025). .It Fl l Ar log_level Specify the log level. The default is 1. All serious errors are logged at log level 0. Major time corrections are logged at log level 1. All @@ -223,6 +232,26 @@ It is difficult to calculate the packet latency for an internet time source and in some cases this can result in time sources which disagree as much as 20ms with each other. If you specify multiple targets and run in debug or a high-logging mode you may observe this issue. +.Sh MULTIPLE SERVERS AND DNS ROUND ROBINS +Multiple servers may be specified in the configuration file. Pool domains +are supported and the same domain name may be specified several times to +connect to several different targets within the pool. Your DNS server +must rotate IPs for this to work properly (all +.Ux +name servers will rotate IPs). +.Nm +will automatically weed out any duplicate IPs. +.Pp +When two or more time sources are configured, +.Nm +will do a quorum-based sanity check on its best pick and fail the server if +its offset deviates significantly from other servers. +.Pp +If a server fails, +.Nm +will relookup its domain name and attempt to reconnect to it. +To avoid overloading servers due to packet routing snafus, reconnections +can take upwards of an hour to cycle. .Sh CONFIGURATION FILE The .Pa /etc/dntpd.conf diff --git a/usr.sbin/dntpd/main.c b/usr.sbin/dntpd/main.c index 26a4738511..c48e61abbf 100644 --- a/usr.sbin/dntpd/main.c +++ b/usr.sbin/dntpd/main.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/usr.sbin/dntpd/main.c,v 1.10 2007/06/25 21:33:36 dillon Exp $ + * $DragonFly: src/usr.sbin/dntpd/main.c,v 1.11 2007/06/26 02:40:20 dillon Exp $ */ #include "defs.h" @@ -56,6 +56,7 @@ int no_update_opt = 0; /* do not make any actual updates */ int min_sleep_opt = 5; /* 5 seconds minimum poll interval */ int nom_sleep_opt = 300; /* 5 minutes nominal poll interval */ int max_sleep_opt = 1800; /* 30 minutes maximum poll interval */ +double insane_deviation = 0.5; /* 0.5 seconds of deviation == insane */ const char *config_opt; /* config file */ const char *pid_opt = "/var/run/dntpd.pid"; @@ -77,7 +78,7 @@ main(int ac, char **av) /* * Process Options */ - while ((ch = getopt(ac, av, "df:l:np:qstFL:QST:")) != -1) { + while ((ch = getopt(ac, av, "df:i:l:np:qstFL:QST:")) != -1) { switch(ch) { case 'd': debug_opt = 1; @@ -93,6 +94,9 @@ main(int ac, char **av) case 'f': config_opt = optarg; break; + case 'i': + insane_deviation = strtod(optarg, NULL); + break; case 'l': debug_level = strtol(optarg, NULL, 0); break; -- 2.11.4.GIT