diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2015-04-07 08:29:34 +0000 |
---|---|---|
committer | <> | 2015-04-13 18:52:43 +0000 |
commit | b2ccf8dd31d1457ae9f0ae270054117179220370 (patch) | |
tree | 4ccd4a16d5e9ef5869630ba624e822665a6e248c /ntpd/ntp_loopfilter.c | |
parent | bdab5265fcbf3f472545073a23f8999749a9f2b9 (diff) | |
download | ntp-master.tar.gz |
Imported from /home/lorry/working-area/delta_ntp/ntp-4.2.8p2.tar.gz.HEADntp-4.2.8p2master
Diffstat (limited to 'ntpd/ntp_loopfilter.c')
-rw-r--r-- | ntpd/ntp_loopfilter.c | 188 |
1 files changed, 140 insertions, 48 deletions
diff --git a/ntpd/ntp_loopfilter.c b/ntpd/ntp_loopfilter.c index 87db726..e47f83b 100644 --- a/ntpd/ntp_loopfilter.c +++ b/ntpd/ntp_loopfilter.c @@ -8,6 +8,9 @@ # include <config.h> #endif +#ifdef USE_SNPRINTB +# include <util.h> +#endif #include "ntpd.h" #include "ntp_io.h" #include "ntp_unixtime.h" @@ -43,7 +46,7 @@ #define CLOCK_LIMIT 30 /* poll-adjust threshold */ #define CLOCK_PGATE 4. /* poll-adjust gate */ #define PPS_MAXAGE 120 /* kernel pps signal timeout (s) */ -#define FREQTOD(x) ((x) / 65536e6) /* NTP to double */ +#define FREQTOD(x) ((x) / 65536e6) /* NTP to double */ #define DTOFREQ(x) ((int32)((x) * 65536e6)) /* double to NTP */ /* @@ -103,7 +106,8 @@ /* * Program variables that can be tinkered. */ -double clock_max = CLOCK_MAX; /* step threshold */ +double clock_max_back = CLOCK_MAX; /* step threshold */ +double clock_max_fwd = CLOCK_MAX; /* step threshold */ double clock_minstep = CLOCK_MINSTEP; /* stepout threshold */ double clock_panic = CLOCK_PANIC; /* panic threshold */ double clock_phi = CLOCK_PHI; /* dispersion rate (s/s) */ @@ -149,8 +153,10 @@ int kern_enable = TRUE; /* kernel support enabled */ int hardpps_enable; /* kernel PPS discipline enabled */ int ext_enable; /* external clock enabled */ int pps_stratum; /* pps stratum */ -int allow_panic = FALSE; /* allow panic correction */ -int mode_ntpdate = FALSE; /* exit on first clock set */ +int kernel_status; /* from ntp_adjtime */ +int allow_panic = FALSE; /* allow panic correction (-g) */ +int force_step_once = FALSE; /* always step time once at startup (-G) */ +int mode_ntpdate = FALSE; /* exit on first clock set (-q) */ int freq_cnt; /* initial frequency clamp */ int freq_set; /* initial set frequency switch */ @@ -182,6 +188,21 @@ static sigjmp_buf env; /* environment var. for pll_trap() */ #endif /* SIGSYS */ #endif /* KERNEL_PLL */ +static void +sync_status(const char *what, int ostatus, int nstatus) +{ + char obuf[256], nbuf[256], tbuf[1024]; +#if defined(USE_SNPRINTB) && defined (STA_FMT) + snprintb(obuf, sizeof(obuf), STA_FMT, ostatus); + snprintb(nbuf, sizeof(nbuf), STA_FMT, nstatus); +#else + snprintf(obuf, sizeof(obuf), "%04x", ostatus); + snprintf(nbuf, sizeof(nbuf), "%04x", nstatus); +#endif + snprintf(tbuf, sizeof(tbuf), "%s status: %s -> %s", what, obuf, nbuf); + report_event(EVNT_KERN, NULL, tbuf); +} + /* * file_name - return pointer to non-relative portion of this C file pathname */ @@ -189,7 +210,9 @@ static char *file_name(void) { if (this_file == NULL) { (void)strncpy(relative_path, __FILE__, PATH_MAX); - for (this_file=relative_path; *this_file && ! isalnum(*this_file); this_file++) ; + for (this_file=relative_path; + *this_file && ! isalnum((unsigned char)*this_file); + this_file++) ; } return this_file; } @@ -259,47 +282,69 @@ ntp_adjtime_error_handler( } break; #ifdef TIME_OK - case TIME_OK: /* 0 no leap second warning */ - /* OK means OK */ + case TIME_OK: /* 0: synchronized, no leap second warning */ + /* msyslog(LOG_INFO, "kernel reports time is synchronized normally"); */ break; +#else +# warning TIME_OK is not defined #endif #ifdef TIME_INS - case TIME_INS: /* 1 positive leap second warning */ - msyslog(LOG_INFO, "%s: %s line %d: kernel reports positive leap second warning state", - caller, file_name(), line - ); + case TIME_INS: /* 1: positive leap second warning */ + msyslog(LOG_INFO, "kernel reports leap second insertion scheduled"); break; +#else +# warning TIME_INS is not defined #endif #ifdef TIME_DEL - case TIME_DEL: /* 2 negative leap second warning */ - msyslog(LOG_INFO, "%s: %s line %d: kernel reports negative leap second warning state", - caller, file_name(), line - ); + case TIME_DEL: /* 2: negative leap second warning */ + msyslog(LOG_INFO, "kernel reports leap second deletion scheduled"); break; +#else +# warning TIME_DEL is not defined #endif #ifdef TIME_OOP - case TIME_OOP: /* 3 leap second in progress */ - msyslog(LOG_INFO, "%s: %s line %d: kernel reports leap second in progress", - caller, file_name(), line - ); + case TIME_OOP: /* 3: leap second in progress */ + msyslog(LOG_INFO, "kernel reports leap second in progress"); break; +#else +# warning TIME_OOP is not defined #endif #ifdef TIME_WAIT - case TIME_WAIT: /* 4 leap second has occured */ - msyslog(LOG_INFO, "%s: %s line %d: kernel reports leap second has occured", - caller, file_name(), line - ); + case TIME_WAIT: /* 4: leap second has occured */ + msyslog(LOG_INFO, "kernel reports leap second has occurred"); break; +#else +# warning TIME_WAIT is not defined #endif #ifdef TIME_ERROR - case TIME_ERROR: /* loss of synchronization */ + case TIME_ERROR: /* 5: unsynchronized, or loss of synchronization */ + /* error (see status word) */ if (pps_call && !(ptimex->status & STA_PPSSIGNAL)) report_event(EVNT_KERN, NULL, "PPS no signal"); errno = saved_errno; DPRINTF(1, ("kernel loop status (%s) %d %m\n", k_st_flags(ptimex->status), errno)); + /* + * This code may be returned when ntp_adjtime() has just + * been called for the first time, quite a while after + * startup, when ntpd just starts to discipline the kernel + * time. In this case the occurrence of this message + * can be pretty confusing. + * + * HMS: How about a message when we begin kernel processing: + * Determining kernel clock state... + * so an initial TIME_ERROR message is less confising, + * or skipping the first message (ugh), + * or ??? + * msyslog(LOG_INFO, "kernel reports time synchronization lost"); + */ + errno = saved_errno; /* may not be needed */ + msyslog(LOG_INFO, "kernel reports TIME_ERROR: %#x: %s %m", + ptimex->status, k_st_flags(ptimex->status)); break; +#else +# warning TIME_ERROR is not defined #endif default: msyslog(LOG_NOTICE, "%s: %s line %d: unhandled return value %d from ntp_adjtime in %s at line %d", @@ -383,7 +428,8 @@ local_clock( * directly to the terminal. */ if (mode_ntpdate) { - if (fabs(fp_offset) > clock_max && clock_max > 0) { + if ( ( fp_offset > clock_max_fwd && clock_max_fwd > 0) + || (-fp_offset > clock_max_back && clock_max_back > 0)) { step_systime(fp_offset); msyslog(LOG_NOTICE, "ntpd: time set %+.6f s", fp_offset); @@ -432,10 +478,10 @@ local_clock( * threshold (128 ms) and when it does not. Under certain * conditions updates are suspended until the stepout theshold * (900 s) is exceeded. See the documentation on how these - * thresholds interact with commands and command line options. + * thresholds interact with commands and command line options. * * Note the kernel is disabled if step is disabled or greater - * than 0.5 s or in ntpdate mode. + * than 0.5 s or in ntpdate mode. */ osys_poll = sys_poll; if (sys_poll < peer->minpoll) @@ -445,7 +491,14 @@ local_clock( mu = current_time - clock_epoch; clock_frequency = drift_comp; rval = 1; - if (fabs(fp_offset) > clock_max && clock_max > 0) { + if ( ( fp_offset > clock_max_fwd && clock_max_fwd > 0) + || (-fp_offset > clock_max_back && clock_max_back > 0) + || force_step_once ) { + if (force_step_once) { + force_step_once = FALSE; /* we want this only once after startup */ + msyslog(LOG_NOTICE, "Doing intital time step" ); + } + switch (state) { /* @@ -505,7 +558,7 @@ local_clock( * threshold. Note that a single spike greater than the * step threshold is always suppressed, even with a * long time constant. - */ + */ default: snprintf(tbuf, sizeof(tbuf), "%+.6f s", fp_offset); @@ -523,7 +576,6 @@ local_clock( } rstclock(EVNT_SYNC, 0); } else { - /* * The offset is less than the step threshold. Calculate * the jitter as the exponentially weighted offset @@ -585,9 +637,9 @@ local_clock( /* * The PLL frequency gain (numerator) depends on * the minimum of the update interval and Allan - * intercept. This reduces the PLL gain when the + * intercept. This reduces the PLL gain when the * FLL becomes effective. - */ + */ etemp = min(ULOGTOD(allan_xpt), mu); dtemp = 4 * CLOCK_PLL * ULOGTOD(sys_poll); clock_frequency += fp_offset * etemp / (dtemp * @@ -663,16 +715,17 @@ local_clock( * Enable/disable the PPS if requested. */ if (hardpps_enable) { + ntv.status |= (STA_PPSTIME | STA_PPSFREQ); if (!(pll_status & STA_PPSTIME)) - report_event(EVNT_KERN, - NULL, "PPS enabled"); - ntv.status |= STA_PPSTIME | STA_PPSFREQ; + sync_status("PPS enabled", + pll_status, + ntv.status); } else { + ntv.status &= ~(STA_PPSTIME | STA_PPSFREQ); if (pll_status & STA_PPSTIME) - report_event(EVNT_KERN, - NULL, "PPS disabled"); - ntv.status &= ~(STA_PPSTIME | - STA_PPSFREQ); + sync_status("PPS disabled", + pll_status, + ntv.status); } if (sys_leap == LEAP_ADDSECOND) ntv.status |= STA_INS; @@ -685,8 +738,13 @@ local_clock( * the pps. In any case, fetch the kernel offset, * frequency and jitter. */ - if ((ntp_adj_ret = ntp_adjtime(&ntv)) != 0) { - ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, hardpps_enable, 0, __LINE__ - 1); + ntp_adj_ret = ntp_adjtime(&ntv); + /* + * A squeal is a return status < 0, or a state change. + */ + if ((0 > ntp_adj_ret) || (ntp_adj_ret != kernel_status)) { + kernel_status = ntp_adj_ret; + ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, hardpps_enable, 0, __LINE__ - 1); } pll_status = ntv.status; #ifdef STA_NANO @@ -867,7 +925,7 @@ adj_host_clock( clock_offset -= offset_adj; /* * Windows port adj_systime() must be called each second, - * even if the argument is zero, to ease emulation of + * even if the argument is zero, to ease emulation of * adjtime() using Windows' slew API which controls the rate * but does not automatically stop slewing when an offset * has decayed to zero. @@ -896,7 +954,7 @@ rstclock( report_event(trans, NULL, NULL); state = trans; last_offset = clock_offset = offset; - clock_epoch = current_time; + clock_epoch = current_time; } @@ -1142,6 +1200,21 @@ loop_config( break; case LOOP_KERN_CLEAR: +#if 0 /* XXX: needs more review, and how can we get here? */ +#ifndef LOCKCLOCK +# ifdef KERNEL_PLL + if (pll_control && kern_enable) { + memset((char *)&ntv, 0, sizeof(ntv)); + ntv.modes = MOD_STATUS; + ntv.status = STA_UNSYNC; + ntp_adjtime(&ntv); + sync_status("kernel time sync disabled", + pll_status, + ntv.status); + } +# endif /* KERNEL_PLL */ +#endif /* LOCKCLOCK */ +#endif break; /* @@ -1154,12 +1227,12 @@ loop_config( case LOOP_CODEC: /* audio codec frequency (codec) */ clock_codec = freq / 1e6; break; - + case LOOP_PHI: /* dispersion threshold (dispersion) */ clock_phi = freq / 1e6; break; - case LOOP_FREQ: /* initial frequency (freq) */ + case LOOP_FREQ: /* initial frequency (freq) */ init_drift_comp = freq; freq_set++; break; @@ -1180,8 +1253,27 @@ loop_config( break; case LOOP_MAX: /* step threshold (step) */ - clock_max = freq; - if (clock_max == 0 || clock_max > 0.5) + clock_max_fwd = clock_max_back = freq; + if (freq == 0 || freq > 0.5) + select_loop(FALSE); + break; + + case LOOP_MAX_BACK: /* step threshold (step) */ + clock_max_back = freq; + /* + * Leave using the kernel discipline code unless both + * limits are massive. This assumes the reason to stop + * using it is that it's pointless, not that it goes wrong. + */ + if ( (clock_max_back == 0 || clock_max_back > 0.5) + || (clock_max_fwd == 0 || clock_max_fwd > 0.5)) + select_loop(FALSE); + break; + + case LOOP_MAX_FWD: /* step threshold (step) */ + clock_max_fwd = freq; + if ( (clock_max_back == 0 || clock_max_back > 0.5) + || (clock_max_fwd == 0 || clock_max_fwd > 0.5)) select_loop(FALSE); break; @@ -1189,7 +1281,7 @@ loop_config( if (freq < CLOCK_MINSTEP) clock_minstep = CLOCK_MINSTEP; else - clock_minstep = freq; + clock_minstep = freq; break; case LOOP_TICK: /* tick increment (tick) */ |