From 19b3c5be26c969bd6d269812f7ed600cd5f649eb Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Fri, 3 Feb 2012 14:57:25 +0100 Subject: [PATCH] Extend tracking, sources and activity reports --- candm.h | 12 +++++++++++- chrony.texi | 49 ++++++++++++++++++++++++++++++++++++------------- client.c | 31 ++++++++++++++++++++++++------- cmdmon.c | 16 ++++++++++++++++ ntp_sources.c | 5 +++-- reference.c | 44 +++++++++++++++++++++++--------------------- reports.h | 6 ++++++ sources.c | 17 +++++++++++++++++ 8 files changed, 136 insertions(+), 44 deletions(-) diff --git a/candm.h b/candm.h index fdff31d..a6edc6e 100644 --- a/candm.h +++ b/candm.h @@ -369,7 +369,8 @@ typedef struct { and used also instead of integer microseconds, new commands: modify stratum, modify polltarget, modify maxdelaydevratio, reselect, reselectdistance - Version 5 : auth data moved to the end of the packet to allow different hashes + Version 5 : auth data moved to the end of the packet to allow hashes with + different sizes, extended sources, tracking and activity reports */ #define PROTO_VERSION_NUMBER 5 @@ -508,12 +509,17 @@ typedef struct { #define RPY_SD_ST_CANDIDATE 4 #define RPY_SD_ST_OUTLYER 5 +#define RPY_SD_FLAG_NOSELECT 0x1 +#define RPY_SD_FLAG_PREFER 0x2 + typedef struct { IPAddr ip_addr; uint16_t poll; uint16_t stratum; uint16_t state; uint16_t mode; + uint16_t flags; + uint16_t reachability; uint32_t since_sample; Float orig_latest_meas; Float latest_meas; @@ -527,11 +533,14 @@ typedef struct { uint32_t stratum; Timeval ref_time; Float current_correction; + Float last_offset; + Float rms_offset; Float freq_ppm; Float resid_freq_ppm; Float skew_ppm; Float root_delay; Float root_dispersion; + Float last_update_interval; int32_t EOR; } RPY_Tracking; @@ -619,6 +628,7 @@ typedef struct { int32_t offline; int32_t burst_online; int32_t burst_offline; + int32_t unresolved; int32_t EOR; } RPY_Activity; diff --git a/chrony.texi b/chrony.texi index 5984f7b..2ef766f 100644 --- a/chrony.texi +++ b/chrony.texi @@ -1523,6 +1523,9 @@ The syntax is corrtimeratio 10 @end example +The current remaining correction is shown in the @code{tracking} report +(@pxref{tracking command}) as the @code{System time} value. + @c }}} @c {{{ deny @node deny directive @@ -3021,7 +3024,7 @@ If the auto_offline option is used in specifying some of the servers/peers, the @code{activity} command may be useful for detecting when all of them have entered the offline state after the PPP link has been disconnected. -The report shows the number of servers/peers in 4 states: +The report shows the number of servers/peers in 5 states: @itemize @item @code{online} : the server/peer is currently online (i.e. assumed by chronyd to be reachable) @@ -3033,6 +3036,9 @@ server/peer will be returned to the online state. @item @code{burst_offline} : a burst command has been initiated for the server/peer and is being performed; after the burst is complete, the server/peer will be returned to the offline state. +@item @code{unresolved} : the name of the server/peer wasn't resolved to an +address yet; this server is not visible in the @code{sources} and +@code{sourcestats} reports. @end itemize @c }}} @c {{{ add peer @@ -3942,11 +3948,11 @@ columns. @example @group 210 Number of sources = 3 -MS Name/IP address Stratum Poll LastRx Last sample -======================================================================= -^+ a.b.c 3 6 47m -9491us[-6983us] +/- 159ms -^+ d.e.f 3 6 47m +32ms[ +35ms] +/- 274ms -^* g.h.i 2 6 47m +8839us[ +11ms] +/- 214ms +MS Name/IP address Stratum Poll Reach LastRx Last sample +=============================================================================== +#* GPS0 0 4 377 11 -479ns[ -621ns] +/- 134ns +^? a.b.c 2 6 377 23 -923us[ -924us] +/- 43ms +^+ d.e.f 1 6 377 21 -2629us[-2619us] +/- 86ms @end group @end example @@ -3987,10 +3993,18 @@ that a measurement is being made every 64 seconds. @code{chronyd} automatically varies the polling rate in response to prevailing conditions. +@item Reach +This shows the source's reachability register printed as octal number. The +register has 8 bits and is updated on every received or missed packet from +the source. A value of 377 indicates that a valid reply was received for all +from the last eight transmissions. + @item LastRx This column shows how long ago the last sample was received from the source. This is normally in seconds. The letters @code{m}, @code{h}, -@code{d} or @code{y} indicate minutes, hours, days or years. +@code{d} or @code{y} indicate minutes, hours, days or years. A value +of 10 years indicates there were no samples received from this source +yet. @item Last sample This column shows the offset between the local clock and the source at @@ -4091,8 +4105,10 @@ performance. An example of the output is shown below. @example Reference ID : 1.2.3.4 (a.b.c) Stratum : 3 -Ref time (UTC) : Sun May 17 06:13:11 1998 -System time : 0.000000000 seconds fast of NTP time +Ref time (UTC) : Fri Feb 3 15:00:29 2012 +System time : 0.000001501 seconds slow of NTP time +Last offset : -0.000001632 seconds +RMS offset : 0.000002360 seconds Frequency : 331.898 ppm fast Residual freq : 0.004 ppm Skew : 0.154 ppm @@ -4118,7 +4134,7 @@ computer, so the computer in the example is two hops away (i.e. @code{a.b.c} is a stratum-2 and is synchronised from a stratum-1). @item Ref time -This is the time (GMT) at which the last measurement from the reference +This is the time (UTC) at which the last measurement from the reference source was processed. @item System time @@ -4139,9 +4155,13 @@ On systems such as Solaris and SunOS, @code{chronyd} has no means to adjust the fundamental rate of the system clock, so keeps the system time correct by periodically making offsets to it as though an error had been measured. The build up of these offsets will be observed in this -report. On systems such as Linux where @code{chronyd} can adjust the -fundamental rate of the system clock, this value will show zero unless a -very recent measurement has shown the system to be error. +report. + +@item Last offset +This is the estimated local offset on the last clock update. + +@item RMS offset +This is a long-term average of the offset value. @item Frequency The `frequency' is the rate by which the system's clock would be would @@ -4195,6 +4215,9 @@ stratum-1 computer is correct) is given by clock_error <= root_dispersion + (0.5 * |root_delay|) @end example +@item Update interval +This is the interval between the last two clock updates. + @end table @c }}} @c {{{ trimrtc diff --git a/client.c b/client.c index 7884991..c7bc458 100644 --- a/client.c +++ b/client.c @@ -1670,7 +1670,7 @@ process_cmd_sources(char *line) IPAddr ip_addr; uint32_t latest_meas_ago; uint16_t poll, stratum; - uint16_t state, mode; + uint16_t state, mode, flags, reachability; char hostname_buf[50]; /* Check whether to output verbose headers */ @@ -1692,10 +1692,10 @@ process_cmd_sources(char *line) printf("|| | | \n"); } - printf("MS Name/IP address Stratum Poll LastRx Last sample\n"); - printf("============================================================================\n"); + printf("MS Name/IP address Stratum Poll Reach LastRx Last sample\n"); + printf("===============================================================================\n"); - /* "MS NNNNNNNNNNNNNNNNNNNNNNNNN SS PP RRRR SSSSSSS[SSSSSSS] +/- SSSSSS" */ + /* "MS NNNNNNNNNNNNNNNNNNNNNNNNNNN SS PP RRR RRRR SSSSSSS[SSSSSSS] +/- SSSSSS" */ for (i=0; i 0.0) ? "slow" : "fast"); + printf("Last offset : %.9f seconds\n", last_offset); + printf("RMS offset : %.9f seconds\n", rms_offset); freq_ppm = UTI_FloatNetworkToHost(reply.data.tracking.freq_ppm); resid_freq_ppm = UTI_FloatNetworkToHost(reply.data.tracking.resid_freq_ppm); skew_ppm = UTI_FloatNetworkToHost(reply.data.tracking.skew_ppm); root_delay = UTI_FloatNetworkToHost(reply.data.tracking.root_delay); root_dispersion = UTI_FloatNetworkToHost(reply.data.tracking.root_dispersion); + last_update_interval = UTI_FloatNetworkToHost(reply.data.tracking.last_update_interval); printf("Frequency : %.3f ppm %s\n", fabs(freq_ppm), (freq_ppm < 0.0) ? "slow" : "fast"); printf("Residual freq : %.3f ppm\n", resid_freq_ppm); printf("Skew : %.3f ppm\n", skew_ppm); printf("Root delay : %.6f seconds\n", root_delay); printf("Root dispersion : %.6f seconds\n", root_dispersion); + printf("Update interval : %.1f seconds\n", last_update_interval); return 1; } return 0; @@ -2357,11 +2372,13 @@ process_cmd_activity(const char *line) "%ld sources online\n" "%ld sources offline\n" "%ld sources doing burst (return to online)\n" - "%ld sources doing burst (return to offline)\n", + "%ld sources doing burst (return to offline)\n" + "%ld sources with unknown address\n", (long) ntohl(reply.data.activity.online), (long) ntohl(reply.data.activity.offline), (long) ntohl(reply.data.activity.burst_online), - (long) ntohl(reply.data.activity.burst_offline)); + (long) ntohl(reply.data.activity.burst_offline), + (long) ntohl(reply.data.activity.unresolved)); return 1; } return 0; diff --git a/cmdmon.c b/cmdmon.c index 7810fef..0755a47 100644 --- a/cmdmon.c +++ b/cmdmon.c @@ -1062,6 +1062,18 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message) tx_message->data.source_data.mode = htons(RPY_SD_MD_REF); break; } + switch (report.sel_option) { + case RPT_NORMAL: + tx_message->data.source_data.flags = htons(0); + break; + case RPT_PREFER: + tx_message->data.source_data.flags = htons(RPY_SD_FLAG_PREFER); + break; + case RPT_NOSELECT: + tx_message->data.source_data.flags = htons(RPY_SD_FLAG_PREFER); + break; + } + tx_message->data.source_data.reachability = htons(report.reachability); tx_message->data.source_data.since_sample = htonl(report.latest_meas_ago); tx_message->data.source_data.orig_latest_meas = UTI_FloatHostToNetwork(report.orig_latest_meas); tx_message->data.source_data.latest_meas = UTI_FloatHostToNetwork(report.latest_meas); @@ -1373,11 +1385,14 @@ handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message) tx_message->data.tracking.stratum = htonl(rpt.stratum); UTI_TimevalHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time); tx_message->data.tracking.current_correction = UTI_FloatHostToNetwork(rpt.current_correction); + tx_message->data.tracking.last_offset = UTI_FloatHostToNetwork(rpt.last_offset); + tx_message->data.tracking.rms_offset = UTI_FloatHostToNetwork(rpt.rms_offset); tx_message->data.tracking.freq_ppm = UTI_FloatHostToNetwork(rpt.freq_ppm); tx_message->data.tracking.resid_freq_ppm = UTI_FloatHostToNetwork(rpt.resid_freq_ppm); tx_message->data.tracking.skew_ppm = UTI_FloatHostToNetwork(rpt.skew_ppm); tx_message->data.tracking.root_delay = UTI_FloatHostToNetwork(rpt.root_delay); tx_message->data.tracking.root_dispersion = UTI_FloatHostToNetwork(rpt.root_dispersion); + tx_message->data.tracking.last_update_interval = UTI_FloatHostToNetwork(rpt.last_update_interval); } /* ================================================== */ @@ -1679,6 +1694,7 @@ handle_activity(CMD_Request *rx_message, CMD_Reply *tx_message) tx_message->data.activity.offline = htonl(report.offline); tx_message->data.activity.burst_online = htonl(report.burst_online); tx_message->data.activity.burst_offline = htonl(report.burst_offline); + tx_message->data.activity.unresolved = htonl(report.unresolved); tx_message->status = htons(STT_SUCCESS); tx_message->reply = htons(RPY_ACTIVITY); } diff --git a/ntp_sources.c b/ntp_sources.c index ca84ff4..65294b6 100644 --- a/ntp_sources.c +++ b/ntp_sources.c @@ -665,9 +665,10 @@ NSR_GetActivityReport(RPT_ActivityReport *report) } } - /* Add unresolved sources to offline count */ + report->unresolved = 0; + for (us = unresolved_sources; us; us = us->next) { - report->offline++; + report->unresolved++; } return; diff --git a/reference.c b/reference.c index fa9be8b..093b6be 100644 --- a/reference.c +++ b/reference.c @@ -55,6 +55,9 @@ static double our_root_dispersion; static double max_update_skew; +static double last_offset; +static double avg2_offset; + static double correction_time_ratio; /* Flag indicating that we are initialised */ @@ -705,6 +708,11 @@ REF_SetReference(int stratum, } last_ref_update_interval = update_interval; + last_offset = our_offset; + if (avg2_offset > 0.0) + avg2_offset += 0.1 * (our_offset * our_offset - avg2_offset); + else + avg2_offset = our_offset * our_offset; /* And now set the freq and offset to zero */ our_frequency = 0.0; @@ -917,6 +925,21 @@ REF_GetTrackingReport(RPT_TrackingReport *rep) LCL_GetOffsetCorrection(&now_raw, &correction, NULL); UTI_AddDoubleToTimeval(&now_raw, correction, &now_cooked); + rep->ref_id = 0; + rep->ip_addr.family = IPADDR_UNSPEC; + rep->stratum = 0; + rep->ref_time.tv_sec = 0; + rep->ref_time.tv_usec = 0; + rep->current_correction = correction; + rep->freq_ppm = LCL_ReadAbsoluteFrequency(); + rep->resid_freq_ppm = 0.0; + rep->skew_ppm = 0.0; + rep->root_delay = 0.0; + rep->root_dispersion = 0.0; + rep->last_update_interval = last_ref_update_interval; + rep->last_offset = last_offset; + rep->rms_offset = sqrt(avg2_offset); + if (are_we_synchronised) { UTI_DiffTimevalsToDouble(&elapsed, &now_cooked, &our_ref_time); @@ -926,8 +949,6 @@ REF_GetTrackingReport(RPT_TrackingReport *rep) rep->ip_addr = our_ref_ip; rep->stratum = our_stratum; rep->ref_time = our_ref_time; - rep->current_correction = correction; - rep->freq_ppm = LCL_ReadAbsoluteFrequency(); rep->resid_freq_ppm = 1.0e6 * our_residual_freq; rep->skew_ppm = 1.0e6 * our_skew; rep->root_delay = our_root_delay; @@ -939,26 +960,7 @@ REF_GetTrackingReport(RPT_TrackingReport *rep) rep->ip_addr.family = IPADDR_UNSPEC; rep->stratum = local_stratum; rep->ref_time = now_cooked; - rep->current_correction = correction; - rep->freq_ppm = LCL_ReadAbsoluteFrequency(); - rep->resid_freq_ppm = 0.0; - rep->skew_ppm = 0.0; - rep->root_delay = 0.0; rep->root_dispersion = LCL_GetSysPrecisionAsQuantum(); - - } else { - - rep->ref_id = 0; - rep->ip_addr.family = IPADDR_UNSPEC; - rep->stratum = 0; - rep->ref_time.tv_sec = 0; - rep->ref_time.tv_usec = 0; - rep->current_correction = correction; - rep->freq_ppm = LCL_ReadAbsoluteFrequency(); - rep->resid_freq_ppm = 0.0; - rep->skew_ppm = 0.0; - rep->root_delay = 0.0; - rep->root_dispersion = 0.0; } } diff --git a/reports.h b/reports.h index 4b4f55e..4322a9c 100644 --- a/reports.h +++ b/reports.h @@ -38,7 +38,9 @@ typedef struct { int poll; enum {RPT_NTP_CLIENT, RPT_NTP_PEER, RPT_LOCAL_REFERENCE} mode; enum {RPT_SYNC, RPT_UNREACH, RPT_FALSETICKER, RPT_JITTERY, RPT_CANDIDATE} state; + enum {RPT_NORMAL, RPT_PREFER, RPT_NOSELECT} sel_option; + int reachability; unsigned long latest_meas_ago; /* seconds */ double orig_latest_meas; /* seconds */ double latest_meas; /* seconds */ @@ -51,11 +53,14 @@ typedef struct { unsigned long stratum; struct timeval ref_time; double current_correction; + double last_offset; + double rms_offset; double freq_ppm; double resid_freq_ppm; double skew_ppm; double root_delay; double root_dispersion; + double last_update_interval; } RPT_TrackingReport; typedef struct { @@ -113,6 +118,7 @@ typedef struct { int offline; int burst_online; int burst_offline; + int unresolved; } RPT_ActivityReport; #endif /* GOT_REPORTS_H */ diff --git a/sources.c b/sources.c index bfe7e3c..890d87a 100644 --- a/sources.c +++ b/sources.c @@ -1110,6 +1110,23 @@ SRC_ReportSource(int index, RPT_SourceReport *report, struct timeval *now) assert(0); break; } + + switch (src->sel_option) { + case SRC_SelectNormal: + report->sel_option = RPT_NOSELECT; + break; + case SRC_SelectPrefer: + report->sel_option = RPT_PREFER; + break; + case SRC_SelectNoselect: + report->sel_option = RPT_NOSELECT; + break; + default: + assert(0); + } + + report->reachability = src->reachability; + /* Call stats module to fill out estimates */ SST_DoSourceReport(src->stats, report, now);