From: Dave Hart Date: Mon, 21 Nov 2011 09:35:28 +0000 (+0000) Subject: [Bug 2050] Orphan mode stratum counting to infinity. X-Git-Tag: NTP_4_2_6P5_RC2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ae36303060b866a3f9a5ab359fe78233baa0d223;p=thirdparty%2Fntp.git [Bug 2050] Orphan mode stratum counting to infinity. bk: 4eca1b60hHB5nWd3Pp8_UEeji6tuKQ --- diff --git a/ChangeLog b/ChangeLog index b79cdd102..b81fa6d8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +--- + +* [Bug 2050] Orphan mode stratum counting to infinity. + --- (4.2.6p5-RC1) 2011/10/18 Released by Harlan Stenn diff --git a/include/ntp_types.h b/include/ntp_types.h index 9ace91fe9..cbc0c1c16 100644 --- a/include/ntp_types.h +++ b/include/ntp_types.h @@ -57,17 +57,23 @@ typedef unsigned int u_int; #if (SIZEOF_INT == 4) # ifndef int32 # define int32 int +# define INT32_MIN INT_MIN +# define INT32_MAX INT_MAX # endif # ifndef u_int32 # define u_int32 unsigned int +# define U_INT32_MAX UINT_MAX # endif #else /* not sizeof(int) == 4 */ # if (SIZEOF_LONG == 4) # ifndef int32 # define int32 long +# define INT32_MIN LONG_MIN +# define INT32_MAX LONG_MAX # endif # ifndef u_int32 # define u_int32 unsigned long +# define U_INT32_MAX ULONG_MAX # endif # else /* not sizeof(long) == 4 */ # include "Bletch: what's 32 bits on this machine?" diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index 9651fc050..55177915d 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -2204,7 +2204,7 @@ clock_select(void) double high, low; double seljitter; double synch[NTP_MAXASSOC], error[NTP_MAXASSOC]; - double orphdist = 1e10; + double orphmet = 2.0 * U_INT32_MAX; /* 2x is greater than */ struct peer *osys_peer = NULL; struct peer *sys_prefer = NULL; /* prefer peer */ struct peer *typesystem = NULL; @@ -2279,20 +2279,43 @@ clock_select(void) continue; /* - * If this is an orphan, choose the one with - * the lowest metric defined as the IPv4 address - * or the first 64 bits of the hashed IPv6 address. + * If this peer is an orphan parent, elect the + * one with the lowest metric defined as the + * IPv4 address or the first 64 bits of the + * hashed IPv6 address. To ensure convergence + * on the same selected orphan, consider as + * well that this system may have the lowest + * metric and be the orphan parent. If this + * system wins, sys_peer will be NULL to trigger + * orphan mode in timer(). */ if (peer->stratum == sys_orphan) { - double ftemp; + u_int32 localmet; + u_int32 peermet; - ftemp = addr2refid(&peer->srcadr); - if (ftemp < orphdist) { + localmet = peer->dstadr->addr_refid; + peermet = addr2refid(&peer->srcadr); + if (peermet < localmet && + peermet < orphmet) { typeorphan = peer; - orphdist = ftemp; + orphmet = peermet; } continue; } + + /* + * If this peer could have the orphan parent + * as a synchronization ancestor, exclude it + * from selection to avoid forming a + * synchronization loop within the orphan mesh, + * triggering stratum climb to infinity + * instability. Peers at stratum higher than + * the orphan stratum could have the orphan + * parent in ancestry so are excluded. + * See http://bugs.ntp.org/2050 + */ + if (peer->stratum > sys_orphan) + continue; #ifdef REFCLOCK /* * The following are special cases. We deal diff --git a/ntpd/ntp_timer.c b/ntpd/ntp_timer.c index d5a1206d0..3c2c832b1 100644 --- a/ntpd/ntp_timer.c +++ b/ntpd/ntp_timer.c @@ -302,8 +302,8 @@ timer(void) /* * Orphan mode is active when enabled and when no servers less - * than the orphan statum are available. A server with no other - * synchronization source is an orphan It shows offset zero and + * than the orphan stratum are available. A server with no other + * synchronization source is an orphan. It shows offset zero and * reference ID the loopback address. */ if (sys_orphan < STRATUM_UNSPEC && sys_peer == NULL) {