]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 2050] Orphan mode stratum counting to infinity.
authorDave Hart <hart@ntp.org>
Mon, 21 Nov 2011 09:35:28 +0000 (09:35 +0000)
committerDave Hart <hart@ntp.org>
Mon, 21 Nov 2011 09:35:28 +0000 (09:35 +0000)
bk: 4eca1b60hHB5nWd3Pp8_UEeji6tuKQ

ChangeLog
include/ntp_types.h
ntpd/ntp_proto.c
ntpd/ntp_timer.c

index b79cdd102cc0413b41cfeb779e712fb714ad42d0..b81fa6d8d8dc6d37141b1d53731da0db2b11e459 100644 (file)
--- 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 <stenn@ntp.org>
 
index 9ace91fe949b95419af3e55b9b4b45b45f5b0c44..cbc0c1c1693d8cce6ca2c69c23ec380f4a1dc2a3 100644 (file)
@@ -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?"
index 9651fc050516f22631c4964be01fecac702d84a1..55177915daf61052a9e1aef9a5a3ca5df9c0852f 100644 (file)
@@ -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
index d5a1206d06a24218df4b85ba1b9c16f521763132..3c2c832b198617f0bce98297f1eb745dda582e61 100644 (file)
@@ -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) {