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
#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;
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;
int32_t offline;
int32_t burst_online;
int32_t burst_offline;
+ int32_t unresolved;
int32_t EOR;
} RPY_Activity;
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
@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)
@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
@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
@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
@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
(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
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
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
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 */
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<n_sources; i++) {
request.command = htons(REQ_SOURCE_DATA);
stratum = ntohs(reply.data.source_data.stratum);
state = ntohs(reply.data.source_data.state);
mode = ntohs(reply.data.source_data.mode);
+ flags = ntohs(reply.data.source_data.flags);
+ reachability = ntohs(reply.data.source_data.reachability);
latest_meas_ago = ntohl(reply.data.source_data.since_sample);
orig_latest_meas = UTI_FloatNetworkToHost(reply.data.source_data.orig_latest_meas);
latest_meas = UTI_FloatNetworkToHost(reply.data.source_data.latest_meas);
default:
printf(" ");
}
+ switch (flags) {
+ default:
+ break;
+ }
- printf(" %-25s %2d %2d ", hostname_buf, stratum, poll);
+ printf(" %-27s %2d %2d %3o ", hostname_buf, stratum, poll, reachability);
print_seconds(latest_meas_ago);
printf(" ");
print_signed_nanoseconds(latest_meas);
struct tm ref_time_tm;
unsigned long a, b, c, d;
double 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;
request.command = htons(REQ_TRACKING);
if (request_reply(&request, &reply, RPY_TRACKING, 0)) {
ref_time_tm = *gmtime((time_t *)&ref_time.tv_sec);
printf("Ref time (UTC) : %s", asctime(&ref_time_tm));
correction = UTI_FloatNetworkToHost(reply.data.tracking.current_correction);
+ last_offset = UTI_FloatNetworkToHost(reply.data.tracking.last_offset);
+ rms_offset = UTI_FloatNetworkToHost(reply.data.tracking.rms_offset);
printf("System time : %.9f seconds %s of NTP time\n", fabs(correction),
(correction > 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;
"%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;
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);
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);
}
/* ================================================== */
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);
}
}
}
- /* Add unresolved sources to offline count */
+ report->unresolved = 0;
+
for (us = unresolved_sources; us; us = us->next) {
- report->offline++;
+ report->unresolved++;
}
return;
static double max_update_skew;
+static double last_offset;
+static double avg2_offset;
+
static double correction_time_ratio;
/* Flag indicating that we are initialised */
}
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;
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);
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;
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;
}
}
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 */
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 {
int offline;
int burst_online;
int burst_offline;
+ int unresolved;
} RPT_ActivityReport;
#endif /* GOT_REPORTS_H */
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);