From 14c8f07629adb7b574f12e72106c2a24f05a7b22 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Fri, 7 Oct 2016 15:40:49 +0200 Subject: [PATCH] ntp: save source of local timestamps Introduce a new structure for local timestamps that will hold the timestamp with its estimated error and also its source (daemon, kernel or HW). While at it, reorder parameters of the functions that accept the timestamps. --- ntp_core.c | 101 +++++++++++++++++++++++--------------------------- ntp_core.h | 30 ++++++++++----- ntp_io.c | 25 +++++++------ ntp_sources.c | 16 ++++---- ntp_sources.h | 8 ++-- 5 files changed, 93 insertions(+), 87 deletions(-) diff --git a/ntp_core.c b/ntp_core.c index 6137731..e1aafc9 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -154,7 +154,7 @@ struct NCR_Instance_Record { parameters for the current reference. (It must be stored relative to local time to permit frequency and offset adjustments to be made when we trim the local clock). */ - struct timespec local_rx; + NTP_Local_Timestamp local_rx; /* Local timestamp when we last transmitted a packet to the source. We store two versions. The first is in NTP format, and is used @@ -165,7 +165,7 @@ struct NCR_Instance_Record { local clock frequency/offset changes, and use this for computing statistics about the source when a return packet arrives. */ NTP_int64 local_ntp_tx; - struct timespec local_tx; + NTP_Local_Timestamp local_tx; /* The instance record in the main source management module. This performs the statistical analysis on the samples we generate */ @@ -401,7 +401,7 @@ start_initial_timeout(NCR_Instance inst) the interval between packets at least as long as the current polling interval */ SCH_GetLastEventTime(&now, NULL, NULL); - last_tx = UTI_DiffTimespecsToDouble(&now, &inst->local_tx); + last_tx = UTI_DiffTimespecsToDouble(&now, &inst->local_tx.ts); if (last_tx < 0.0) last_tx = 0.0; delay = get_transmit_delay(inst, 0, 0.0) - last_tx; @@ -531,7 +531,9 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar result->tx_suspended = 1; result->opmode = params->online ? MD_ONLINE : MD_OFFLINE; result->local_poll = result->minpoll; - UTI_ZeroTimespec(&result->local_tx); + UTI_ZeroTimespec(&result->local_tx.ts); + result->local_tx.err = 0.0; + result->local_tx.source = NTP_TS_DAEMON; NCR_ResetInstance(result); @@ -589,7 +591,9 @@ NCR_ResetInstance(NCR_Instance instance) instance->remote_orig.lo = 0; instance->local_ntp_tx.hi = 0; instance->local_ntp_tx.lo = 0; - UTI_ZeroTimespec(&instance->local_rx); + UTI_ZeroTimespec(&instance->local_rx.ts); + instance->local_rx.err = 0.0; + instance->local_rx.source = NTP_TS_DAEMON; if (instance->local_poll != instance->minpoll) { instance->local_poll = instance->minpoll; @@ -797,11 +801,10 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ int auth_mode, /* The authentication mode */ uint32_t key_id, /* The authentication key ID */ NTP_int64 *orig_ts, /* Originate timestamp (from received packet) */ - struct timespec *local_rx, /* Local time request packet was received */ - struct timespec *local_tx, /* RESULT : Time this reply - is sent as local time, or - NULL if don't want to - know */ + NTP_Local_Timestamp *local_rx, /* Local time request packet was received */ + NTP_Local_Timestamp *local_tx, /* RESULT : Time this reply is sent as + local time, or NULL if don't want to + know */ NTP_int64 *local_ntp_tx, /* RESULT : Time reply sent as NTP timestamp (including adjustment to @@ -865,9 +868,9 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ if (smooth_time) { our_ref_id = NTP_REFID_SMOOTH; UTI_AddDoubleToTimespec(&our_ref_time, smooth_offset, &our_ref_time); - UTI_AddDoubleToTimespec(local_rx, smooth_offset, &local_receive); + UTI_AddDoubleToTimespec(&local_rx->ts, smooth_offset, &local_receive); } else { - local_receive = *local_rx; + local_receive = local_rx->ts; } /* Generate transmit packet */ @@ -950,7 +953,9 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ ret = NIO_SendPacket(&message, where_to, from, length, local_tx != NULL); if (local_tx) { - *local_tx = local_transmit; + local_tx->ts = local_transmit; + local_tx->err = 0.0; + local_tx->source = NTP_TS_DAEMON; } if (local_ntp_tx) { @@ -1192,8 +1197,8 @@ check_packet_auth(NTP_Packet *pkt, int length, /* ================================================== */ static int -receive_packet(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, - NCR_Instance inst, NTP_Local_Address *local_addr, int length) +receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length) { int pkt_leap; uint32_t pkt_refid, pkt_key_id; @@ -1335,7 +1340,7 @@ receive_packet(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, UTI_AverageDiffTimespecs(&remote_receive, &remote_transmit, &remote_average, &remote_interval); - UTI_AverageDiffTimespecs(&inst->local_tx, rx_ts, + UTI_AverageDiffTimespecs(&inst->local_tx.ts, &rx_ts->ts, &local_average, &local_interval); /* In our case, we work out 'delay' as the worst case delay, @@ -1366,7 +1371,7 @@ receive_packet(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, skew = (source_freq_hi - source_freq_lo) / 2.0; /* and then calculate peer dispersion */ - dispersion = precision + rx_ts_err + skew * fabs(local_interval); + dispersion = precision + rx_ts->err + skew * fabs(local_interval); /* Additional tests required to pass before accumulating the sample */ @@ -1396,7 +1401,7 @@ receive_packet(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, pkt_refid != UTI_IPToRefid(&local_addr->ip_addr); } else { offset = delay = dispersion = 0.0; - sample_time = *rx_ts; + sample_time = rx_ts->ts; testA = testB = testC = testD = 0; } @@ -1484,7 +1489,7 @@ receive_packet(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, /* And now, requeue the timer */ if (inst->opmode != MD_OFFLINE) { delay_time = get_transmit_delay(inst, 0, - UTI_DiffTimespecsToDouble(&inst->local_rx, &inst->local_tx)); + UTI_DiffTimespecsToDouble(&inst->local_rx.ts, &inst->local_tx.ts)); if (kod_rate) { /* Back off for a while and stop ongoing burst */ @@ -1550,14 +1555,8 @@ receive_packet(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, and it relates to a source we have an ongoing protocol exchange with */ int -NCR_ProcessRxKnown -(NTP_Packet *message, /* the received message */ - struct timespec *rx_ts, /* timestamp at time of receipt */ - double rx_ts_err, - NCR_Instance inst, /* the instance record for this peer/server */ - NTP_Local_Address *local_addr, /* the receiving address */ - int length /* the length of the received packet */ - ) +NCR_ProcessRxKnown(NCR_Instance inst, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length) { int pkt_mode, proc_packet, proc_as_unknown; @@ -1664,10 +1663,9 @@ NCR_ProcessRxKnown return 0; } - return receive_packet(message, rx_ts, rx_ts_err, inst, local_addr, length); + return receive_packet(inst, local_addr, rx_ts, message, length); } else if (proc_as_unknown) { - NCR_ProcessRxUnknown(message, rx_ts, rx_ts_err, &inst->remote_addr, - local_addr, length); + NCR_ProcessRxUnknown(&inst->remote_addr, local_addr, rx_ts, message, length); /* It's not a reply to our request, don't return success */ return 0; } else { @@ -1682,14 +1680,8 @@ NCR_ProcessRxKnown and it relates to a source we don't know (not our server or peer) */ void -NCR_ProcessRxUnknown -(NTP_Packet *message, /* the received message */ - struct timespec *rx_ts, /* timestamp at time of receipt */ - double rx_ts_err, /* assumed error in the timestamp */ - NTP_Remote_Address *remote_addr, - NTP_Local_Address *local_addr, - int length /* the length of the received packet */ - ) +NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length) { NTP_Mode pkt_mode, my_mode; int valid_auth, log_index; @@ -1730,7 +1722,7 @@ NCR_ProcessRxUnknown return; } - log_index = CLG_LogNTPAccess(&remote_addr->ip_addr, rx_ts); + log_index = CLG_LogNTPAccess(&remote_addr->ip_addr, &rx_ts->ts); /* Don't reply to all requests if the rate is excessive */ if (log_index >= 0 && CLG_LimitNTPResponseRate(log_index)) { @@ -1771,12 +1763,12 @@ NCR_ProcessRxUnknown /* ================================================== */ static void -update_tx_timestamp(struct timespec *tx_ts, struct timespec *new_tx_ts, +update_tx_timestamp(NTP_Local_Timestamp *tx_ts, NTP_Local_Timestamp *new_tx_ts, NTP_int64 *local_ntp_tx, NTP_Packet *message) { double delay; - if (UTI_IsZeroTimespec(tx_ts)) { + if (UTI_IsZeroTimespec(&tx_ts->ts)) { DEBUG_LOG(LOGF_NtpCore, "Unexpected TX update"); return; } @@ -1788,7 +1780,7 @@ update_tx_timestamp(struct timespec *tx_ts, struct timespec *new_tx_ts, return; } - delay = UTI_DiffTimespecsToDouble(new_tx_ts, tx_ts); + delay = UTI_DiffTimespecsToDouble(&new_tx_ts->ts, &tx_ts->ts); if (delay < 0.0 || delay > MAX_TX_DELAY) { DEBUG_LOG(LOGF_NtpCore, "Unacceptable TX delay %.9f", delay); @@ -1803,8 +1795,8 @@ update_tx_timestamp(struct timespec *tx_ts, struct timespec *new_tx_ts, /* ================================================== */ void -NCR_ProcessTxKnown(NTP_Packet *message, struct timespec *tx_ts, double tx_ts_err, - NCR_Instance inst, NTP_Local_Address *local_addr, int length) +NCR_ProcessTxKnown(NCR_Instance inst, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *tx_ts, NTP_Packet *message, int length) { NTP_Mode pkt_mode; @@ -1815,8 +1807,7 @@ NCR_ProcessTxKnown(NTP_Packet *message, struct timespec *tx_ts, double tx_ts_err /* Server and passive mode packets are responses to unknown sources */ if (pkt_mode != MODE_CLIENT && pkt_mode != MODE_ACTIVE) { - NCR_ProcessTxUnknown(message, tx_ts, tx_ts_err, &inst->remote_addr, - local_addr, length); + NCR_ProcessTxUnknown(&inst->remote_addr, local_addr, tx_ts, message, length); return; } @@ -1826,8 +1817,8 @@ NCR_ProcessTxKnown(NTP_Packet *message, struct timespec *tx_ts, double tx_ts_err /* ================================================== */ void -NCR_ProcessTxUnknown(NTP_Packet *message, struct timespec *tx_ts, double tx_ts_err, - NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length) +NCR_ProcessTxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *tx_ts, NTP_Packet *message, int length) { /* Nothing to do yet */ DEBUG_LOG(LOGF_NtpCore, "Process TX unknown"); @@ -1840,10 +1831,10 @@ NCR_SlewTimes(NCR_Instance inst, struct timespec *when, double dfreq, double dof { double delta; - if (!UTI_IsZeroTimespec(&inst->local_rx)) - UTI_AdjustTimespec(&inst->local_rx, when, &inst->local_rx, &delta, dfreq, doffset); - if (!UTI_IsZeroTimespec(&inst->local_tx)) - UTI_AdjustTimespec(&inst->local_tx, when, &inst->local_tx, &delta, dfreq, doffset); + if (!UTI_IsZeroTimespec(&inst->local_rx.ts)) + UTI_AdjustTimespec(&inst->local_rx.ts, when, &inst->local_rx.ts, &delta, dfreq, doffset); + if (!UTI_IsZeroTimespec(&inst->local_tx.ts)) + UTI_AdjustTimespec(&inst->local_tx.ts, when, &inst->local_tx.ts, &delta, dfreq, doffset); } /* ================================================== */ @@ -2141,13 +2132,15 @@ broadcast_timeout(void *arg) { BroadcastDestination *destination; NTP_int64 orig_ts; - struct timespec recv_ts; + NTP_Local_Timestamp recv_ts; destination = ARR_GetElement(broadcasts, (long)arg); orig_ts.hi = 0; orig_ts.lo = 0; - UTI_ZeroTimespec(&recv_ts); + UTI_ZeroTimespec(&recv_ts.ts); + recv_ts.source = NTP_TS_DAEMON; + recv_ts.err = 0.0; transmit_packet(MODE_BROADCAST, 6 /* FIXME: should this be log2(interval)? */, NTP_VERSION, 0, 0, &orig_ts, &recv_ts, NULL, NULL, diff --git a/ntp_core.h b/ntp_core.h index 9e8e76e..4d0c214 100644 --- a/ntp_core.h +++ b/ntp_core.h @@ -38,6 +38,18 @@ 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; + NTP_Timestamp_Source source; +} NTP_Local_Timestamp; + /* This is a private data type used for storing the instance record for each source that we are chiming with */ typedef struct NCR_Instance_Record *NCR_Instance; @@ -63,25 +75,23 @@ extern void NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remot /* This routine is called when a new packet arrives off the network, and it relates to a source we have an ongoing protocol exchange with */ -extern int NCR_ProcessRxKnown(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, - NCR_Instance inst, NTP_Local_Address *local_addr, int length); +extern int NCR_ProcessRxKnown(NCR_Instance inst, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length); /* This routine is called when a new packet arrives off the network, and we do not recognize its source */ -extern void NCR_ProcessRxUnknown(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, - NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, - int length); +extern void NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length); /* This routine is called when a packet is sent to a source we have an ongoing protocol exchange with */ -extern void NCR_ProcessTxKnown(NTP_Packet *message, struct timespec *tx_ts, double tx_ts_err, - NCR_Instance inst, NTP_Local_Address *local_addr, int length); +extern void NCR_ProcessTxKnown(NCR_Instance inst, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *tx_ts, NTP_Packet *message, int length); /* This routine is called when a packet is sent to a destination we do not recognize */ -extern void NCR_ProcessTxUnknown(NTP_Packet *message, struct timespec *tx_ts, double tx_ts_err, - NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, - int length); +extern void NCR_ProcessTxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *tx_ts, NTP_Packet *message, int length); /* Slew receive and transmit times in instance records */ extern void NCR_SlewTimes(NCR_Instance inst, struct timespec *when, double dfreq, double doffset); diff --git a/ntp_io.c b/ntp_io.c index 22618e9..07f6a00 100644 --- a/ntp_io.c +++ b/ntp_io.c @@ -552,12 +552,13 @@ process_message(struct msghdr *hdr, int length, int sock_fd) { NTP_Remote_Address remote_addr; NTP_Local_Address local_addr; + NTP_Local_Timestamp local_ts; + struct timespec sched_ts; struct cmsghdr *cmsg; - struct timespec local_ts, sched_ts; - double local_ts_err; - SCH_GetLastEventTime(&local_ts, &local_ts_err, NULL); - sched_ts = local_ts; + SCH_GetLastEventTime(&local_ts.ts, &local_ts.err, NULL); + local_ts.source = NTP_TS_DAEMON; + sched_ts = local_ts.ts; if (hdr->msg_namelen > sizeof (union sockaddr_in46)) { DEBUG_LOG(LOGF_NtpIO, "Truncated source address"); @@ -604,7 +605,8 @@ process_message(struct msghdr *hdr, int length, int sock_fd) memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv)); UTI_TimevalToTimespec(&tv, &ts); - LCL_CookTime(&ts, &local_ts, &local_ts_err); + LCL_CookTime(&ts, &local_ts.ts, &local_ts.err); + local_ts.source = NTP_TS_KERNEL; } #endif @@ -613,22 +615,23 @@ process_message(struct msghdr *hdr, int length, int sock_fd) struct timespec ts; memcpy(&ts, CMSG_DATA(cmsg), sizeof (ts)); - LCL_CookTime(&ts, &local_ts, &local_ts_err); + LCL_CookTime(&ts, &local_ts.ts, &local_ts.err); + local_ts.source = NTP_TS_KERNEL; } #endif } - DEBUG_LOG(LOGF_NtpIO, "Received %d bytes from %s:%d to %s fd=%d delay=%.9f", + DEBUG_LOG(LOGF_NtpIO, "Received %d bytes from %s:%d to %s fd=%d tss=%d delay=%.9f", length, UTI_IPToString(&remote_addr.ip_addr), remote_addr.port, - UTI_IPToString(&local_addr.ip_addr), local_addr.sock_fd, - UTI_DiffTimespecsToDouble(&sched_ts, &local_ts)); + UTI_IPToString(&local_addr.ip_addr), local_addr.sock_fd, local_ts.source, + UTI_DiffTimespecsToDouble(&sched_ts, &local_ts.ts)); /* Just ignore the packet if it's not of a recognized length */ if (length < NTP_NORMAL_PACKET_LENGTH || length > sizeof (NTP_Receive_Buffer)) return; - NSR_ProcessRx((NTP_Packet *)hdr->msg_iov[0].iov_base, &local_ts, local_ts_err, - &remote_addr, &local_addr, length); + NSR_ProcessRx(&remote_addr, &local_addr, &local_ts, + (NTP_Packet *)hdr->msg_iov[0].iov_base, length); } /* ================================================== */ diff --git a/ntp_sources.c b/ntp_sources.c index e42f32a..00f922b 100644 --- a/ntp_sources.c +++ b/ntp_sources.c @@ -776,8 +776,8 @@ NSR_GetLocalRefid(IPAddr *address) /* This routine is called by ntp_io when a new packet arrives off the network, possibly with an authentication tail */ void -NSR_ProcessRx(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, - NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length) +NSR_ProcessRx(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length) { SourceRecord *record; struct SourcePool *pool; @@ -789,7 +789,7 @@ NSR_ProcessRx(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, if (found == 2) { /* Must match IP address AND port number */ record = get_record(slot); - if (!NCR_ProcessRxKnown(message, rx_ts, rx_ts_err, record->data, local_addr, length)) + if (!NCR_ProcessRxKnown(record->data, local_addr, rx_ts, message, length)) return; if (record->tentative) { @@ -810,15 +810,15 @@ NSR_ProcessRx(NTP_Packet *message, struct timespec *rx_ts, double rx_ts_err, } } } else { - NCR_ProcessRxUnknown(message, rx_ts, rx_ts_err, remote_addr, local_addr, length); + NCR_ProcessRxUnknown(remote_addr, local_addr, rx_ts, message, length); } } /* ================================================== */ void -NSR_ProcessTx(NTP_Packet *message, struct timespec *tx_ts, double tx_ts_err, - NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length) +NSR_ProcessTx(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *tx_ts, NTP_Packet *message, int length) { SourceRecord *record; int slot, found; @@ -827,9 +827,9 @@ NSR_ProcessTx(NTP_Packet *message, struct timespec *tx_ts, double tx_ts_err, if (found == 2) { /* Must match IP address AND port number */ record = get_record(slot); - NCR_ProcessTxKnown(message, tx_ts, tx_ts_err, record->data, local_addr, length); + NCR_ProcessTxKnown(record->data, local_addr, tx_ts, message, length); } else { - NCR_ProcessTxUnknown(message, tx_ts, tx_ts_err, remote_addr, local_addr, length); + NCR_ProcessTxUnknown(remote_addr, local_addr, tx_ts, message, length); } } diff --git a/ntp_sources.h b/ntp_sources.h index 924a7a5..424eab6 100644 --- a/ntp_sources.h +++ b/ntp_sources.h @@ -87,13 +87,13 @@ extern void NSR_RefreshAddresses(void); extern uint32_t NSR_GetLocalRefid(IPAddr *address); /* This routine is called by ntp_io when a new packet arrives off the network */ -extern void NSR_ProcessRx(NTP_Packet *message, struct timespec *rx_ts, double tx_ts_err, - NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length); +extern void NSR_ProcessRx(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *rx_ts, NTP_Packet *message, int length); /* This routine is called by ntp_io when a packet was sent to the network and an accurate transmit timestamp was captured */ -extern void NSR_ProcessTx(NTP_Packet *message, struct timespec *tx_ts, double tx_ts_err, - NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length); +extern void NSR_ProcessTx(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, + NTP_Local_Timestamp *tx_ts, NTP_Packet *message, int length); /* Initialisation function */ extern void NSR_Initialise(void);