]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
leap second cleanup from Dave Mills
authorHarlan Stenn <stenn@ntp.org>
Tue, 19 Jun 2007 22:50:51 +0000 (18:50 -0400)
committerHarlan Stenn <stenn@ntp.org>
Tue, 19 Jun 2007 22:50:51 +0000 (18:50 -0400)
bk: 46785dcbQhoAawSmhvA8-F8KLLg7UQ

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

index 4d0771ab3fa05a676b9251aa14c55978c490d3db..579f75b93122b5198e91628e996d4347f33efbb1 100644 (file)
@@ -405,7 +405,6 @@ extern int  sys_floor;              /* cluster stratum floor */
 extern int     sys_ceiling;            /* cluster stratum ceiling */
 extern u_char  sys_ttl[];              /* ttl mapping vector */
 extern int     sys_ttlmax;             /* max ttl mapping vector index */
-extern int     leap_next;              /* leap consensus */
 
 /*
  * Statistics counters
index ea9f4e529666e1eac172e7c3729dbaacd4ef7966..122234e4c49c4641a8e2b63fe2586b6638e6f814 100644 (file)
@@ -133,7 +133,6 @@ double      clock_codec;            /* audio codec frequency (sambles/s) */
 u_long sys_clocktime;          /* last system clock update */
 u_long pps_control;            /* last pps update */
 u_int  sys_tai;                /* TAI offset from UTC (s) */
-u_long sys_leapin;             /* seconds at next leap (s) */
 static void rstclock (int, u_long, double); /* transition function */
 
 #ifdef KERNEL_PLL
@@ -528,9 +527,6 @@ local_clock(
                if (ext_enable) {
                        ntv.modes = MOD_STATUS;
                } else {
-                       struct tm *tm = NULL;
-                       time_t tstamp;
-
 #ifdef STA_NANO
                        ntv.modes = MOD_BITS | MOD_NANO;
 #else /* STA_NANO */
@@ -565,24 +561,6 @@ local_clock(
                            sys_rootdispersion) * 1e6);
                        ntv.status = STA_PLL;
 
-                       /*
-                        * Set the leap bits in the status word, but
-                        * only on the last day of June or December.
-                        */
-                       tstamp = peer->rec.l_ui - JAN_1970;
-                       tm = gmtime(&tstamp);
-                       if (tm != NULL) {
-                               if ((tm->tm_mon + 1 == 6 &&
-                                   tm->tm_mday == 30) || (tm->tm_mon +
-                                   1 == 12 && tm->tm_mday == 31)) {
-                                       if (leap_next & LEAP_ADDSECOND)
-                                               ntv.status |= STA_INS;
-                                       else if (leap_next &
-                                           LEAP_DELSECOND)
-                                               ntv.status |= STA_DEL;
-                               }
-                       }
-
                        /*
                         * If the PPS signal is up and enabled, light
                         * the frequency bit. If the PPS driver is
@@ -598,6 +576,17 @@ local_clock(
                                ntv.status &= ~(STA_PPSFREQ |
                                    STA_PPSTIME);
                        }
+
+                       /*
+                        * If less than 23 hours remain before a leap,
+                        * set the kernel leap bits.
+                        */
+                       if (leap_sec > 0 && leap_sec < 23 * 3600) {
+                               if (sys_leap == LEAP_ADDSECOND)
+                                       ntv.status |= STA_INS;
+                               else if (sys_leap == LEAP_DELSECOND)
+                                       ntv.status |= STA_DEL;
+                       }
                }
 
                /*
@@ -1005,12 +994,11 @@ loop_config(
                clock_codec = freq;
                break;
 
-       case LOOP_LEAP:                 /* arm leap insert */
+       case LOOP_LEAP:                 /* set kernel TAI offset */
 #if defined(STA_NANO) && NTP_API == 4
                if (pll_control && kern_enable) {
-                       memset(&ntv, 0, sizeof(ntv));
                        ntv.modes = MOD_TAI;
-                       ntv.constant = sys_tai - 1;
+                       ntv.constant = sys_tai;
                        ntp_adjtime(&ntv);
                }
 #endif /* STA_NANO */
index 9f387a53debe0ba1983dd40da2d82e2c97efc9c5..f25cdae63e650c97a66918a0fcf8905010233ba1 100644 (file)
@@ -66,9 +66,10 @@ static       double sys_maxdist = MAXDISTANCE; /* selection threshold (s) */
 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_ins;               /* seconds at next leap */
 u_long leap_sec;               /* leap countdown */
+static int leap_next;          /* leap consensus */
+static int leap_sw;            /* leap is from file */
 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 */
@@ -1318,30 +1319,55 @@ clock_update(void)
         * at the last offset measurement.
         */
        case 1:
-
                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 no leap is scheduled and the leap is triggered
+                * from the leapseconds file, schedule a leap for the
+                * last entry in the file, but only if it is in the
+                * future. If triggered by upstream server leap bits and
+                * the number of bits is at least the sanity threshold,
+                * schedule a leap for the end of the current month.
                 */
+               get_systime(&now);
                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;
+                       if (leap_ins > now.l_ui) {
+                               if (leap_sw == 0) {
+                                       leap_sw++;
                                        sys_tai--;
+                                       loop_config(LOOP_LEAP, sys_tai);
                                }
+                               if (leap_ins - now.l_ui < 28 * 86400)
+                                       leap_sec = leap_ins - now.l_ui;
+                       } else if (leap_next >= sys_minsane) {
+                               leap_sec = leap_month(now.l_ui);
                        }
+                       if (leap_sec > 0)
+                               msyslog(LOG_NOTICE,
+                                   "leap second armed %lu s",
+                                   leap_sec);
+                               
+
+               /*
+                * If the leap was not triggered from the leapsecond
+                * file, cancel the leap if the server leap bits grow
+                * dim.
+                */
+               } else if (!leap_sw && leap_next < sys_minsane) {
+                       leap_sec = 0;
                }
 
+printf("xxx %d %d %d %d %d %lu\n", sys_leap, sys_tai, leap_sw, sys_minsane, leap_next, leap_sec);
+
+               /*
+                * If this is the first time the clock is set,
+                * reset the leap bits.
+                */
+               if (sys_leap == LEAP_NOTINSYNC)
+                       sys_leap = LEAP_NOWARNING;
+
                /*
                 * In orphan mode the stratum defaults to the orphan
                 * stratum. The root delay is set to a random value
@@ -1523,9 +1549,7 @@ peer_crypto_clear(
        if (peer->pkey != NULL)
                EVP_PKEY_free(peer->pkey);
        peer->pkey = NULL;
-
-       peer->digest = NULL;    /* XXX MEMLEAK? check whether this needs to be freed in any way - never was freed */
-
+       peer->digest = NULL;            /* digest * is a constant */
        if (peer->subject != NULL)
                free(peer->subject);
        peer->subject = NULL;
@@ -3203,13 +3227,14 @@ init_proto(void)
         */
        sys_leap = LEAP_NOTINSYNC;
        sys_stratum = STRATUM_UNSPEC;
+       sys_peer = NULL;
+       sys_rootdelay = 0;
+       sys_rootdispersion = 0;
        memcpy(&sys_refid, "INIT", 4);
        sys_precision = (s_char)default_get_precision();
        sys_jitter = LOGTOD(sys_precision);
-       sys_rootdelay = 0;
        sys_orphandelay = (double)(ntp_random() & 0xffff) / 65536. *
            sys_maxdist;
-       sys_rootdispersion = 0;
        L_CLR(&sys_reftime);
        sys_peer = NULL;
        sys_survivors = 0;
index e29db71cf1711f051b83d03cfec6235f272b4a76..60fa693c48c593eae55a8bb8a0533a8daefbb87b 100644 (file)
@@ -60,9 +60,10 @@ u_char       sys_revoke = KEY_REVOKE;        /* keys revoke timeout (log2 s) */
 volatile u_long alarm_overflow;
 
 #define MINUTE 60
-#define HOUR   (60*60)
+#define HOUR   (60 * 60)
 
-u_long current_time;
+u_long current_time;           /* seconds since startup */
+static int tai_sw;             /* kernel TAI switch */
 
 /*
  * Stats.  Number of overflows and number of calls to transmit().
@@ -311,13 +312,16 @@ timer(void)
         * Leapseconds.
         */
        if (leap_sec > 0) {
-               if (leap_sec < 86400 * 28)
-                       sys_leap = LEAP_ADDSECOND;
-               if (leap_sec < 86400)
-                       loop_config(LOOP_LEAP, sys_tai);
+               sys_leap = LEAP_ADDSECOND;
                leap_sec--;
-       } else {
-               sys_leap = LEAP_NOWARNING;
+               if (leap_sec == 0) {
+                       sys_leap = LEAP_NOWARNING;
+                       if (sys_tai > 0) {
+                               sys_tai++;
+                               msyslog(LOG_NOTICE, "TAI offset %d s",
+                                   sys_tai);
+                       }
+               }
        }
 
        /*
index 9a5484333b0db636df9c93edb765e0755e72ce10..ec0cc355a2be1cf990629fec476d68a48f0c2eaa 100644 (file)
 # include <descrip.h>
 #endif /* VMS */
 
-#define        MAX_LEAP        100     /* max TAI offset (s) */
-
 /*
- * This contains odds and ends.  Right now the only thing you'll find
- * in here is the hourly stats printer and some code to support
- * rereading the keys file, but I may eventually put other things in
- * here such as code to do something with the leap bits.
+ * Defines used by the leapseconds stuff
  */
+#define        MAX_TAI 100                     /* max TAI offset (s) */
+#define        L_DAY   86400UL                 /* seconds per day */
+#define        L_YEAR  (L_DAY * 365)           /* days per year */
+#define        L_LYEAR (L_YEAR + L_DAY)        /* days per leap year */
+#define        L_4YEAR (L_LYEAR + 3 * L_YEAR)  /* days per leap cycle */
+#define        L_CENT  (L_4YEAR * 25)          /* days per century */
+
 /*
- * Name of the keys file
+ * This contains odds and ends, including the hourly stats, various
+ * configuration items, leapseconds stuff, etc.
  */
-static char *key_file_name;
-
 /*
- * The name of the drift_comp file and the temporary.
+ * File names
  */
-static char *stats_drift_file;
-static char *stats_temp_file;
-int stats_write_period = 3600; /* # of seconds between writes. */
-static double prev_drift_comp;
+static char *key_file_name;            /* keys file name */
+static char *stats_drift_file;         /* frequency file name */
+static char *stats_temp_file;          /* temp frequency file name */
+int stats_write_period = 3600;         /* seconds between writes. */
 
 /*
  * Statistics file stuff
@@ -72,13 +73,6 @@ static double prev_drift_comp;
 # define MAXPATHLEN 256
 #endif
 
-static char statsdir[MAXPATHLEN] = NTP_VAR;
-
-static FILEGEN peerstats;
-static FILEGEN loopstats;
-static FILEGEN clockstats;
-static FILEGEN rawstats;
-static FILEGEN sysstats;
 #ifdef DEBUG_TIMING
 static FILEGEN timingstats;
 #endif
@@ -86,6 +80,13 @@ static FILEGEN timingstats;
 static FILEGEN cryptostats;
 #endif /* OPENSSL */
 
+static char statsdir[MAXPATHLEN] = NTP_VAR;
+static FILEGEN peerstats;
+static FILEGEN loopstats;
+static FILEGEN clockstats;
+static FILEGEN rawstats;
+static FILEGEN sysstats;
+
 /*
  * This controls whether stats are written to the fileset. Provided
  * so that ntpdc can turn off stats when the file system fills up. 
@@ -95,8 +96,12 @@ int stats_control;
 /*
  * Initial frequency offset later passed to the loopfilter.
  */
-double old_drift;
+double old_drift;                      /* current frequency */
+static double prev_drift_comp;         /* last frequency update */
 
+/*
+ * Static prototypes
+ */
 static void leap_file(char *);
 
 /*
@@ -120,6 +125,9 @@ init_util(void)
 #ifdef DEBUG_TIMING
        filegen_register(&statsdir[0], "timingstats", &timingstats);
 #endif
+
+leap_file("/etc/leapseconds"); /***** temp for debug *****/
+
 }
 
 
@@ -732,7 +740,7 @@ leap_file(
         * insertion.
         */
        i = TAI_1972;
-       while (i < MAX_LEAP) {
+       while (i < MAX_TAI) {
                dp = fgets(buf, NTP_MAXSTRLEN - 1, str);
                if (dp == NULL)
                        break;
@@ -752,7 +760,8 @@ leap_file(
        }
        fclose(str);
        if (dp != NULL) {
-               msyslog(LOG_INFO, "Leapseconds format error in %s", cp);
+               msyslog(LOG_INFO, "leapseconds format error from %s",
+                   cp);
        } else {
                sys_tai = offset;
                leap_ins = leapsec;
@@ -761,15 +770,10 @@ leap_file(
        }
 }
 
+
 /*
- * leap_month - returns the number of seconds until the end of the month
+ * leap_month - returns 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 */
@@ -783,32 +787,39 @@ leap_month(
                    31}; 
 
        /*
-        * Find current leap cycle
+        * Find current leap cycle.
         */
        ltemp = sec;
-       while (ltemp > L_CENT)
+       while (ltemp >= L_CENT)
                ltemp -= L_CENT;
-       while (ltemp > L_4YEAR)
+       while (ltemp >= L_4YEAR)
                ltemp -= L_4YEAR;
 
        /*
-        * If in leap year, use leap table
+        * We are within four years of the target. If in leap year, use
+        * leap year month table; otherwise, use year month table.
         */
        if (ltemp < L_LYEAR) {
                ptr = lyear;
        } else {
                ptr = year;
                ltemp -= L_LYEAR;
-               while (ltemp > L_YEAR)
+               while (ltemp >= L_YEAR)
                        ltemp -= L_YEAR;
        }
-       while (ltemp > *ptr)
-               ltemp -= *ptr++;
 
-       /* The result is the number of seconds until the end of the
+       /*
+        * We are within one year of the target. Find the month of the
+        * leap.
+        */
+       while (ltemp >= *ptr * L_DAY)
+               ltemp -= *ptr++ * L_DAY;
+
+       /*
+        * The result is the number of seconds until the end of the
         * month when the leap is to occur.
         */
-       return (ltemp);
+       return (*ptr * L_DAY - ltemp - L_DAY);
 }