diff --git a/clientlog.c b/clientlog.c index adf0c59..a6b199e 100644 --- a/clientlog.c +++ b/clientlog.c @@ -126,7 +126,8 @@ static int active; /* RX and TX timestamp saved for clients using interleaved mode */ typedef struct { uint64_t rx_ts; - uint16_t flags; + uint8_t flags; + uint8_t tx_ts_source; uint16_t slew_epoch; int32_t tx_ts_offset; } NtpTimestamps; @@ -155,6 +156,9 @@ static NtpTimestampMap ntp_ts_map; /* Maximum number of timestamps moved in the array to insert a new timestamp */ #define NTPTS_INSERT_LIMIT 64 +/* Maximum expected value of the timestamp source */ +#define MAX_NTP_TS NTP_TS_HARDWARE + /* Global statistics */ static uint32_t total_hits[MAX_SERVICES]; static uint32_t total_drops[MAX_SERVICES]; @@ -773,7 +777,8 @@ push_ntp_tss(uint32_t index) /* ================================================== */ static void -set_ntp_tx_offset(NtpTimestamps *tss, NTP_int64 *rx_ts, struct timespec *tx_ts) +set_ntp_tx(NtpTimestamps *tss, NTP_int64 *rx_ts, struct timespec *tx_ts, + NTP_Timestamp_Source tx_src) { struct timespec ts; @@ -792,12 +797,13 @@ set_ntp_tx_offset(NtpTimestamps *tss, NTP_int64 *rx_ts, struct timespec *tx_ts) tss->tx_ts_offset = (int32_t)ts.tv_nsec + (int32_t)ts.tv_sec * (int32_t)NSEC_PER_SEC; tss->flags |= NTPTS_VALID_TX; + tss->tx_ts_source = tx_src; } /* ================================================== */ static void -get_ntp_tx(NtpTimestamps *tss, struct timespec *tx_ts) +get_ntp_tx(NtpTimestamps *tss, struct timespec *tx_ts, NTP_Timestamp_Source *tx_src) { int32_t offset = tss->tx_ts_offset; NTP_int64 ntp_ts; @@ -814,12 +820,14 @@ get_ntp_tx(NtpTimestamps *tss, struct timespec *tx_ts) } else { UTI_ZeroTimespec(tx_ts); } + + *tx_src = tss->tx_ts_source; } /* ================================================== */ void -CLG_SaveNtpTimestamps(NTP_int64 *rx_ts, struct timespec *tx_ts) +CLG_SaveNtpTimestamps(NTP_int64 *rx_ts, struct timespec *tx_ts, NTP_Timestamp_Source tx_src) { NtpTimestamps *tss; uint32_t i, index; @@ -877,7 +885,7 @@ CLG_SaveNtpTimestamps(NTP_int64 *rx_ts, struct timespec *tx_ts) tss->rx_ts = rx; tss->flags = 0; tss->slew_epoch = ntp_ts_map.slew_epoch; - set_ntp_tx_offset(tss, rx_ts, tx_ts); + set_ntp_tx(tss, rx_ts, tx_ts, tx_src); DEBUG_LOG("Saved RX+TX index=%"PRIu32" first=%"PRIu32" size=%"PRIu32, index, ntp_ts_map.first, ntp_ts_map.size); @@ -921,7 +929,8 @@ CLG_UndoNtpTxTimestampSlew(NTP_int64 *rx_ts, struct timespec *tx_ts) /* ================================================== */ void -CLG_UpdateNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts) +CLG_UpdateNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts, + NTP_Timestamp_Source tx_src) { uint32_t index; @@ -931,13 +940,14 @@ CLG_UpdateNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts) if (!find_ntp_rx_ts(ntp64_to_int64(rx_ts), &index)) return; - set_ntp_tx_offset(get_ntp_tss(index), rx_ts, tx_ts); + set_ntp_tx(get_ntp_tss(index), rx_ts, tx_ts, tx_src); } /* ================================================== */ int -CLG_GetNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts) +CLG_GetNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts, + NTP_Timestamp_Source *tx_src) { NtpTimestamps *tss; uint32_t index; @@ -953,7 +963,7 @@ CLG_GetNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts) if (tss->flags & NTPTS_DISABLED) return 0; - get_ntp_tx(tss, tx_ts); + get_ntp_tx(tss, tx_ts, tx_src); return 1; } diff --git a/clientlog.h b/clientlog.h index 2a5565e..f7d8a48 100644 --- a/clientlog.h +++ b/clientlog.h @@ -46,10 +46,13 @@ extern void CLG_LogAuthNtpRequest(void); extern int CLG_GetNtpMinPoll(void); /* Functions to save and retrieve timestamps for server interleaved mode */ -extern void CLG_SaveNtpTimestamps(NTP_int64 *rx_ts, struct timespec *tx_ts); +extern void CLG_SaveNtpTimestamps(NTP_int64 *rx_ts, struct timespec *tx_ts, + NTP_Timestamp_Source tx_src); extern void CLG_UndoNtpTxTimestampSlew(NTP_int64 *rx_ts, struct timespec *tx_ts); -extern void CLG_UpdateNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts); -extern int CLG_GetNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts); +extern void CLG_UpdateNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts, + NTP_Timestamp_Source tx_src); +extern int CLG_GetNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts, + NTP_Timestamp_Source *tx_src); extern void CLG_DisableNtpTimestamps(NTP_int64 *rx_ts); /* And some reporting functions, for use by chronyc. */ diff --git a/ntp.h b/ntp.h index 52b2ab5..906adc3 100644 --- a/ntp.h +++ b/ntp.h @@ -179,4 +179,11 @@ typedef struct { double root_dispersion; } NTP_Sample; +/* Possible sources of timestamps */ +typedef enum { + NTP_TS_DAEMON = 0, + NTP_TS_KERNEL, + NTP_TS_HARDWARE +} NTP_Timestamp_Source; + #endif /* GOT_NTP_H */ diff --git a/ntp_core.c b/ntp_core.c index 57bda81..05eab94 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -2477,7 +2477,8 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a ntp_rx = message->originate_ts; local_ntp_rx = &ntp_rx; UTI_ZeroTimespec(&local_tx.ts); - interleaved = CLG_GetNtpTxTimestamp(&ntp_rx, &local_tx.ts); + local_tx.source = NTP_TS_DAEMON; + interleaved = CLG_GetNtpTxTimestamp(&ntp_rx, &local_tx.ts, &local_tx.source); tx_ts = &local_tx; if (interleaved) @@ -2500,7 +2501,7 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a return; if (local_ntp_rx) - CLG_SaveNtpTimestamps(local_ntp_rx, &tx_ts->ts); + CLG_SaveNtpTimestamps(local_ntp_rx, &tx_ts->ts, tx_ts->source); } /* ================================================== */ @@ -2578,7 +2579,7 @@ NCR_ProcessTxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a local_ntp_rx = &message->receive_ts; new_tx = *tx_ts; - if (!CLG_GetNtpTxTimestamp(local_ntp_rx, &old_tx.ts)) + if (!CLG_GetNtpTxTimestamp(local_ntp_rx, &old_tx.ts, &old_tx.source)) return; /* Undo a clock adjustment between the RX and TX timestamps to minimise error @@ -2587,7 +2588,7 @@ NCR_ProcessTxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a update_tx_timestamp(&old_tx, &new_tx, local_ntp_rx, NULL, message); - CLG_UpdateNtpTxTimestamp(local_ntp_rx, &new_tx.ts); + CLG_UpdateNtpTxTimestamp(local_ntp_rx, &new_tx.ts, new_tx.source); } /* ================================================== */ diff --git a/ntp_core.h b/ntp_core.h index 33f2bb8..a3c5546 100644 --- a/ntp_core.h +++ b/ntp_core.h @@ -38,12 +38,6 @@ typedef enum { NTP_SERVER, NTP_PEER } NTP_Source_Type; -typedef enum { - NTP_TS_DAEMON = 0, - NTP_TS_KERNEL, - NTP_TS_HARDWARE -} NTP_Timestamp_Source; - typedef struct { struct timespec ts; double err; diff --git a/test/unit/clientlog.c b/test/unit/clientlog.c index f59e130..e5bf1f4 100644 --- a/test/unit/clientlog.c +++ b/test/unit/clientlog.c @@ -36,6 +36,7 @@ test_unit(void) { uint64_t ts64, prev_first_ts64, prev_last_ts64, max_step; uint32_t index2, prev_first, prev_size; + NTP_Timestamp_Source ts_src, ts_src2; struct timespec ts, ts2; int i, j, k, index, shift; CLG_Service s; @@ -95,7 +96,7 @@ test_unit(void) TEST_CHECK(!ntp_ts_map.timestamps); UTI_ZeroNtp64(&ntp_ts); - CLG_SaveNtpTimestamps(&ntp_ts, NULL); + CLG_SaveNtpTimestamps(&ntp_ts, NULL, 0); TEST_CHECK(ntp_ts_map.timestamps); TEST_CHECK(ntp_ts_map.first == 0); TEST_CHECK(ntp_ts_map.size == 0); @@ -132,8 +133,10 @@ test_unit(void) UTI_ZeroTimespec(&ts); } + ts_src = random() % (MAX_NTP_TS + 1); CLG_SaveNtpTimestamps(&ntp_ts, - UTI_IsZeroTimespec(&ts) ? (random() % 2 ? &ts : NULL) : &ts); + UTI_IsZeroTimespec(&ts) ? (random() % 2 ? &ts : NULL) : &ts, + ts_src); if (j < ntp_ts_map.max_size) { TEST_CHECK(ntp_ts_map.size == j + 1); @@ -144,14 +147,15 @@ test_unit(void) } TEST_CHECK(ntp_ts_map.cached_index == ntp_ts_map.size - 1); TEST_CHECK(get_ntp_tss(ntp_ts_map.size - 1)->slew_epoch == ntp_ts_map.slew_epoch); - TEST_CHECK(CLG_GetNtpTxTimestamp(&ntp_ts, &ts2)); + TEST_CHECK(CLG_GetNtpTxTimestamp(&ntp_ts, &ts2, &ts_src2)); TEST_CHECK(UTI_CompareTimespecs(&ts, &ts2) == 0); + TEST_CHECK(UTI_IsZeroTimespec(&ts) || ts_src == ts_src2); for (k = random() % 4; k > 0; k--) { index2 = random() % ntp_ts_map.size; int64_to_ntp64(get_ntp_tss(index2)->rx_ts, &ntp_ts); if (random() % 2) - TEST_CHECK(CLG_GetNtpTxTimestamp(&ntp_ts, &ts)); + TEST_CHECK(CLG_GetNtpTxTimestamp(&ntp_ts, &ts, &ts_src2)); UTI_Ntp64ToTimespec(&ntp_ts, &ts); UTI_AddDoubleToTimespec(&ts, TST_GetRandomDouble(-1.999, 1.999), &ts); @@ -165,10 +169,12 @@ test_unit(void) 1.0e-9); } - CLG_UpdateNtpTxTimestamp(&ntp_ts, &ts); + ts_src = random() % (MAX_NTP_TS + 1); + CLG_UpdateNtpTxTimestamp(&ntp_ts, &ts, ts_src); - TEST_CHECK(CLG_GetNtpTxTimestamp(&ntp_ts, &ts2)); + TEST_CHECK(CLG_GetNtpTxTimestamp(&ntp_ts, &ts2, &ts_src2)); TEST_CHECK(UTI_CompareTimespecs(&ts, &ts2) == 0); + TEST_CHECK(ts_src == ts_src2); if (random() % 2) { uint16_t prev_epoch = ntp_ts_map.slew_epoch; @@ -181,20 +187,20 @@ test_unit(void) index = random() % (ntp_ts_map.size - 1); if (get_ntp_tss(index)->rx_ts + 1 != get_ntp_tss(index + 1)->rx_ts) { int64_to_ntp64(get_ntp_tss(index)->rx_ts + 1, &ntp_ts); - TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts)); + TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts, &ts_src2)); int64_to_ntp64(get_ntp_tss(index + 1)->rx_ts - 1, &ntp_ts); - TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts)); - CLG_UpdateNtpTxTimestamp(&ntp_ts, &ts); + TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts, &ts_src2)); + CLG_UpdateNtpTxTimestamp(&ntp_ts, &ts, ts_src); CLG_UndoNtpTxTimestampSlew(&ntp_ts, &ts); } } if (random() % 2) { int64_to_ntp64(get_ntp_tss(0)->rx_ts - 1, &ntp_ts); - TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts)); + TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts, &ts_src2)); int64_to_ntp64(get_ntp_tss(ntp_ts_map.size - 1)->rx_ts + 1, &ntp_ts); - TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts)); - CLG_UpdateNtpTxTimestamp(&ntp_ts, &ts); + TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts, &ts_src2)); + CLG_UpdateNtpTxTimestamp(&ntp_ts, &ts, ts_src); CLG_UndoNtpTxTimestampSlew(&ntp_ts, &ts); } } @@ -207,7 +213,7 @@ test_unit(void) while (ntp_ts_map.size < ntp_ts_map.max_size) { ts64 += get_random64() >> (shift + 8); int64_to_ntp64(ts64, &ntp_ts); - CLG_SaveNtpTimestamps(&ntp_ts, NULL); + CLG_SaveNtpTimestamps(&ntp_ts, NULL, 0); if (ntp_ts_map.cached_index + NTPTS_INSERT_LIMIT < ntp_ts_map.size) ts64 = get_ntp_tss(ntp_ts_map.size - 1)->rx_ts; } @@ -228,7 +234,7 @@ test_unit(void) prev_size = ntp_ts_map.size; prev_first_ts64 = get_ntp_tss(0)->rx_ts; prev_last_ts64 = get_ntp_tss(prev_size - 1)->rx_ts; - CLG_SaveNtpTimestamps(&ntp_ts, NULL); + CLG_SaveNtpTimestamps(&ntp_ts, NULL, 0); TEST_CHECK(find_ntp_rx_ts(ts64, &index2)); @@ -259,13 +265,13 @@ test_unit(void) if (random() % 10 == 0) { CLG_DisableNtpTimestamps(&ntp_ts); - TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts)); + TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts, &ts_src2)); } for (k = random() % 10; k > 0; k--) { ts64 = get_random64() >> shift; int64_to_ntp64(ts64, &ntp_ts); - CLG_GetNtpTxTimestamp(&ntp_ts, &ts); + CLG_GetNtpTxTimestamp(&ntp_ts, &ts, &ts_src2); } } @@ -274,8 +280,8 @@ test_unit(void) LCL_ChangeUnknownStep, NULL); TEST_CHECK(ntp_ts_map.size == 0); TEST_CHECK(ntp_ts_map.cached_rx_ts == 0ULL); - TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts)); - CLG_UpdateNtpTxTimestamp(&ntp_ts, &ts); + TEST_CHECK(!CLG_GetNtpTxTimestamp(&ntp_ts, &ts, &ts_src2)); + CLG_UpdateNtpTxTimestamp(&ntp_ts, &ts, ts_src); } }