#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?"
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;
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
/*
* 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) {