]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Leap file fixes from Dave Mills
authorHarlan Stenn <stenn@ntp.org>
Thu, 14 Jun 2007 05:40:14 +0000 (01:40 -0400)
committerHarlan Stenn <stenn@ntp.org>
Thu, 14 Jun 2007 05:40:14 +0000 (01:40 -0400)
bk: 4670d4beZKM2hDQD3TySou_OCkk35g

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

index b03cae2d92c3c830856b0091f970e6ffdfa1e7d5..d7d5b27302c894fb15ea1cf2e3e7c30c68d46208 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+* Leap file fixes from Dave Mills.
 * [Bug 858] Recent leapfile changes broke without OPENSSL.
 * Use a char for DIR_SEP, not a string.
 * [Bug 850] driftfile parsing changes.
index 83e146dc4c716d291dd26ab749efc6b6897eda2f..4d0771ab3fa05a676b9251aa14c55978c490d3db 100644 (file)
@@ -122,7 +122,6 @@ extern      void    loop_config (int, double);
 extern void    huffpuff        (void);
 extern u_long  sys_clocktime;
 extern u_int   sys_tai;
-extern u_long  sys_leapin;
 
 /* ntp_monitor.c */
 extern void    init_mon        (void);
@@ -183,6 +182,8 @@ extern      void    peer_clear      (struct peer *, char *);
 extern void    process_packet  (struct peer *, struct pkt *);
 extern void    clock_select    (void);
 extern void    kod_proto       (void);
+extern u_long  leap_ins;
+extern u_long  leap_sec;
 
 /*
  * there seems to be a bug in the IRIX 4 compiler which prevents
@@ -238,6 +239,7 @@ extern      void    record_loop_stats (double, double, double, double, int);
 extern void    record_clock_stats (struct sockaddr_storage *, const char *);
 extern void    record_raw_stats (struct sockaddr_storage *, struct sockaddr_storage *, l_fp *, l_fp *, l_fp *, l_fp *);
 extern void    record_sys_stats (void);
+extern u_long  leap_month(u_long);
 extern void    record_crypto_stats (struct sockaddr_storage *, const char *);
 #ifdef DEBUG
 extern void    record_timing_stats (const char *);
index 1ab9200a2cafde5dc62dce61143cad5164d1edea..9f387a53debe0ba1983dd40da2d82e2c97efc9c5 100644 (file)
@@ -67,6 +67,8 @@ double        sys_jitter;             /* system jitter (s) */
 static int sys_hopper;         /* anticlockhop counter */
 static int sys_maxhop = MAXHOP; /* anticlockhop counter threshold */
 int    leap_next;              /* leap consensus */
+u_long leap_ins;               /* seconds ar next leap */
+u_long leap_sec;               /* leap countdown */
 keyid_t        sys_private;            /* private value for session seed */
 int    sys_manycastserver;     /* respond to manycast client pkts */
 int    peer_ntpdate;           /* active peers in ntpdate mode */
@@ -1261,6 +1263,7 @@ clock_update(void)
        u_char  oleap;
        u_char  ostratum;
        double  dtemp;
+       l_fp    now;
 
        /*
         * There must be a system peer at this point. If we just changed
@@ -1308,16 +1311,36 @@ clock_update(void)
 
        /*
         * Clock was slewed. Update the system stratum, leap bits, root
-        * delay, root dispersion, reference ID and reference time. If
-        * the leap changes, we gotta reroll the keys. Except for
-        * reference clocks, the minimum dispersion increment is not
-        * less than sys_mindisp.
+        * delay, root dispersion, reference ID and reference time.
+        * Except for reference clocks, the minimum dispersion increment
+        * is not less than sys_mindisp. If a leap is anticipated, read
+        * the system clock because the time now might not be the time
+        * at the last offset measurement.
         */
        case 1:
-               sys_leap = leap_next;
+
                sys_stratum = min(sys_peer->stratum + 1,
                    STRATUM_UNSPEC);
                sys_reftime = sys_peer->rec;
+               get_systime(&now);
+
+               /*
+                * If no leap is scheduled and the number of upstream
+                * leap bits is at least the sanity threshold, schedule
+                * a leap for the end of the current month. If from the
+                * leapseconds file schedule a leap for the last entry
+                * in the file, but only if it is in the future. 
+                */
+               if (leap_sec == 0) {
+                       if (leap_next >= sys_minsane) {
+                               leap_sec = leap_month(now.l_ui);
+                       } else if (leap_ins != 0) {
+                               if (now.l_ui < leap_ins) {
+                                       leap_sec = leap_ins - now.l_ui;
+                                       sys_tai--;
+                               }
+                       }
+               }
 
                /*
                 * In orphan mode the stratum defaults to the orphan
@@ -2166,18 +2189,18 @@ clock_select(void)
         * What remains is a list usually not greater than sys_minclock
         * peers. We want only a peer at the lowest stratum to become
         * the system peer, although all survivors are eligible for the
-        * combining algorithm. Consider each peer in turn and OR the
-        * leap bits on the assumption that, if some of them honk
-        * nonzero bits, they must know what they are doing. Check for
-        * prefer and pps peers at any stratum. Note that the head of
-        * the list is at the lowest stratum and that unsynchronized
-        * peers cannot survive this far.
+        * combining algorithm. Consider each peer in turn and compute
+        * the total number of leap bits. Check for prefer and pps peers
+        * at any stratum. Note that the head of the list is at the
+        * lowest stratum and that unsynchronized peers cannot survive
+        * this far.
         */
        leap_next = 0;
        for (i = 0; i < nlist; i++) {
                peer = peer_list[i];
                sys_survivors++;
-               leap_next |= peer->leap;
+               if (peer->leap == LEAP_ADDSECOND)
+                       leap_next++;
                peer->status = CTL_PST_SEL_SYNCCAND;
                if (peer->flags & FLAG_PREFER)
                        sys_prefer = peer;
index 54a5be21b8aab96bd4793b07f4f38089ab8ee93f..e29db71cf1711f051b83d03cfec6235f272b4a76 100644 (file)
@@ -310,8 +310,15 @@ timer(void)
        /*
         * Leapseconds.
         */
-       if (sys_tai > 0 && current_time == sys_leapin)
-               loop_config(LOOP_LEAP, sys_tai);
+       if (leap_sec > 0) {
+               if (leap_sec < 86400 * 28)
+                       sys_leap = LEAP_ADDSECOND;
+               if (leap_sec < 86400)
+                       loop_config(LOOP_LEAP, sys_tai);
+               leap_sec--;
+       } else {
+               sys_leap = LEAP_NOWARNING;
+       }
 
        /*
         * Garbage collect expired keys.
index f7da0cb808edc933ea5be6572ee645e0d575b041..9a5484333b0db636df9c93edb765e0755e72ce10 100644 (file)
@@ -755,12 +755,62 @@ leap_file(
                msyslog(LOG_INFO, "Leapseconds format error in %s", cp);
        } else {
                sys_tai = offset;
-               sys_leapin = leapsec;
+               leap_ins = leapsec;
                msyslog(LOG_INFO, "TAI offset %d s at %lu from %s",
-                   sys_tai, sys_leapin, cp);
+                   sys_tai, leap_ins, cp);
        }
 }
 
+/*
+ * leap_month - returns the number of seconds until the end of the month
+ */
+#define        L_DAY   86400                   /* seconds per day */
+#define        L_YEAR  L_DAY * 365             /* days per year */
+#define        L_LYEAR L_YEAR + 1              /* days per leap year */
+#define        L_4YEAR L_LYEAR + 3 * L_YEAR    /* days per leap cycle */
+#define        L_CENT  (u_long)L_4YEAR * 25    /* days per century */
+
+u_long
+leap_month(
+       u_long  sec             /* current NTP second */
+       )
+{
+       u_long  ltemp;
+       u_long  *ptr;
+       u_long  year[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,
+                   31}; 
+       u_long  lyear[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30,
+                   31}; 
+
+       /*
+        * Find current leap cycle
+        */
+       ltemp = sec;
+       while (ltemp > L_CENT)
+               ltemp -= L_CENT;
+       while (ltemp > L_4YEAR)
+               ltemp -= L_4YEAR;
+
+       /*
+        * If in leap year, use leap table
+        */
+       if (ltemp < L_LYEAR) {
+               ptr = lyear;
+       } else {
+               ptr = year;
+               ltemp -= L_LYEAR;
+               while (ltemp > L_YEAR)
+                       ltemp -= L_YEAR;
+       }
+       while (ltemp > *ptr)
+               ltemp -= *ptr++;
+
+       /* The result is the number of seconds until the end of the
+        * month when the leap is to occur.
+        */
+       return (ltemp);
+}
+
 
 #ifdef DEBUG_TIMING
 /*