}
}
- if (leap_sec != our_leap_sec) {
+ if (leap_sec != our_leap_sec && !REF_IsLeapSecondClose()) {
LCL_SetLeap(leap_sec);
our_leap_sec = leap_sec;
}
/* ================================================== */
+#define LEAP_SECOND_CLOSE 5
+
+int REF_IsLeapSecondClose(void)
+{
+ struct timeval now, now_raw;
+ time_t t;
+
+ if (!our_leap_sec)
+ return 0;
+
+ SCH_GetLastEventTime(&now, NULL, &now_raw);
+
+ t = now.tv_sec > 0 ? now.tv_sec : -now.tv_sec;
+ if ((t + LEAP_SECOND_CLOSE) % (24 * 3600) < 2 * LEAP_SECOND_CLOSE)
+ return 1;
+
+ t = now_raw.tv_sec > 0 ? now_raw.tv_sec : -now_raw.tv_sec;
+ if ((t + LEAP_SECOND_CLOSE) % (24 * 3600) < 2 * LEAP_SECOND_CLOSE)
+ return 1;
+
+ return 0;
+}
+
+/* ================================================== */
+
void
REF_GetTrackingReport(RPT_TrackingReport *rep)
{
extern void REF_DisableLocal(void);
extern int REF_IsLocalActive(void);
+/* Check if current raw or cooked time is close to a leap second
+ and is better to discard any measurements */
+extern int REF_IsLeapSecondClose(void);
+
extern void REF_GetTrackingReport(RPT_TrackingReport *rep);
#endif /* GOT_REFERENCE_H */
DEBUG_LOG(LOGF_Sources, "ip=[%s] t=%s ofs=%f del=%f disp=%f str=%d",
source_to_string(inst), UTI_TimevalToString(sample_time), -offset, root_delay, root_dispersion, stratum);
+ if (REF_IsLeapSecondClose()) {
+ LOG(LOGS_INFO, LOGF_Sources, "Dropping sample around leap second");
+ return;
+ }
+
/* WE HAVE TO NEGATE OFFSET IN THIS CALL, IT IS HERE THAT THE SENSE OF OFFSET
IS FLIPPED */
SST_AccumulateSample(inst->stats, sample_time, -offset, peer_delay, peer_dispersion, root_delay, root_dispersion, stratum);