Add test for ratio of increase in delay to stddev
Require that the ratio of the increase in delay from the minimum one in the stats data register to the standard deviation of the offsets in the register is less than maxdelaydevratio or the difference between measured offset and predicted offset is larger than the increase in delay. In the allowed delay increase is included also skew and maximum clock frequency error. maxdelaydevratio is 10.0 by default.
This commit is contained in:
parent
feb8811f37
commit
b977c95be4
12 changed files with 112 additions and 9 deletions
14
chrony.texi
14
chrony.texi
|
@ -1828,7 +1828,7 @@ An example line (which actually appears as a single line in the file)
|
|||
from the measurements log file is shown below.
|
||||
|
||||
@example
|
||||
1998-07-22 05:40:50 158.152.1.76 N 8 1111 11 1111 10 10 1 \
|
||||
2010-12-22 05:40:50 158.152.1.76 N 8 1111 111 1111 10 10 1.0 \
|
||||
-4.966e-03 2.296e-01 1.577e-05 1.615e-01 7.446e-03
|
||||
@end example
|
||||
|
||||
|
@ -1837,7 +1837,7 @@ values from the example line above) :
|
|||
|
||||
@enumerate 1
|
||||
@item
|
||||
Date [1998-07-22]
|
||||
Date [2010-12-22]
|
||||
@item
|
||||
Hour:Minute:Second [05:40:50]. Note that the date/time pair is
|
||||
expressed in UTC, not the local time zone.
|
||||
|
@ -1853,8 +1853,8 @@ Stratum of remote computer. [2]
|
|||
@item
|
||||
RFC1305 tests 1 through 4 (1=pass, 0=fail) [1111]
|
||||
@item
|
||||
Tests for maximum delay and maximum delay ratio, against user defined
|
||||
parameters (1=pass, 0=fail) [11]
|
||||
Tests for maximum delay, maximum delay ratio and maximum delay dev ratio,
|
||||
against defined parameters (1=pass, 0=fail) [111]
|
||||
@item
|
||||
RFC1305 tests 5 through 8 (1=pass, 0=fail) [1111]
|
||||
@item
|
||||
|
@ -2595,6 +2595,12 @@ measurements that it has buffered. If a measurement has a round trip
|
|||
delay that is greater than the maxdelayratio times the minimum delay, it
|
||||
will be rejected.
|
||||
|
||||
@item maxdelaydevratio
|
||||
If a measurement has ratio of the increase in round-trip delay from
|
||||
the minimum delay amongst the previous measurements to the standard
|
||||
deviation of the previous measurements that is greater than
|
||||
maxdelaydevratio, it will be rejected. The default is 10.0.
|
||||
|
||||
@item presend
|
||||
If the timing measurements being made by @code{chronyd} are the only
|
||||
network data passing between two computers, you may find that some
|
||||
|
|
8
client.c
8
client.c
|
@ -963,6 +963,11 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
|
|||
break;
|
||||
}
|
||||
|
||||
if (data.params.max_delay_dev_ratio != SRC_DEFAULT_MAXDELAYDEVRATIO) {
|
||||
fprintf(stderr, "Option maxdelaydevratio not supported\n");
|
||||
break;
|
||||
}
|
||||
|
||||
msg->data.ntp_source.port = htonl((unsigned long) data.port);
|
||||
UTI_IPHostToNetwork(&data.ip_addr, &msg->data.ntp_source.ip_addr);
|
||||
msg->data.ntp_source.minpoll = htonl(data.params.minpoll);
|
||||
|
@ -998,6 +1003,9 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
|
|||
case CPS_BadPresend:
|
||||
fprintf(stderr, "Unreadable presend value\n");
|
||||
break;
|
||||
case CPS_BadMaxdelaydevratio:
|
||||
fprintf(stderr, "Unreadable max delay dev ratio value\n");
|
||||
break;
|
||||
case CPS_BadMaxdelayratio:
|
||||
fprintf(stderr, "Unreadable max delay ratio value\n");
|
||||
break;
|
||||
|
|
1
cmdmon.c
1
cmdmon.c
|
@ -1271,6 +1271,7 @@ handle_add_source(NTP_Source_Type type, CMD_Request *rx_message, CMD_Reply *tx_m
|
|||
/* not transmitted in cmdmon protocol yet */
|
||||
params.min_stratum = SRC_DEFAULT_MINSTRATUM;
|
||||
params.poll_target = SRC_DEFAULT_POLLTARGET;
|
||||
params.max_delay_dev_ratio = SRC_DEFAULT_MAXDELAYDEVRATIO;
|
||||
|
||||
status = NSR_AddSource(&rem_addr, type, ¶ms);
|
||||
switch (status) {
|
||||
|
|
|
@ -56,6 +56,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
|
|||
src->params.authkey = INACTIVE_AUTHKEY;
|
||||
src->params.max_delay = SRC_DEFAULT_MAXDELAY;
|
||||
src->params.max_delay_ratio = SRC_DEFAULT_MAXDELAYRATIO;
|
||||
src->params.max_delay_dev_ratio = SRC_DEFAULT_MAXDELAYDEVRATIO;
|
||||
src->params.online = 1;
|
||||
src->params.auto_offline = 0;
|
||||
src->params.iburst = 0;
|
||||
|
@ -123,6 +124,14 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
|
|||
} else {
|
||||
line += n;
|
||||
}
|
||||
} else if (!strncasecmp(cmd, "maxdelaydevratio", 16)) {
|
||||
if (sscanf(line, "%lf%n", &src->params.max_delay_dev_ratio, &n) != 1) {
|
||||
result = CPS_BadMaxdelaydevratio;
|
||||
ok = 0;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
/* This MUST come before the following one ! */
|
||||
} else if (!strncasecmp(cmd, "maxdelayratio", 13)) {
|
||||
if (sscanf(line, "%lf%n", &src->params.max_delay_ratio, &n) != 1) {
|
||||
|
|
|
@ -42,6 +42,7 @@ typedef enum {
|
|||
CPS_BadMinpoll,
|
||||
CPS_BadMaxpoll,
|
||||
CPS_BadPresend,
|
||||
CPS_BadMaxdelaydevratio,
|
||||
CPS_BadMaxdelayratio,
|
||||
CPS_BadMaxdelay,
|
||||
CPS_BadKey,
|
||||
|
|
3
conf.c
3
conf.c
|
@ -391,6 +391,9 @@ parse_source(const char *line, NTP_Source_Type type)
|
|||
case CPS_BadPresend:
|
||||
LOG(LOGS_WARN, LOGF_Configure, "Unreadable presend value at line %d", line_number);
|
||||
break;
|
||||
case CPS_BadMaxdelaydevratio:
|
||||
LOG(LOGS_WARN, LOGF_Configure, "Unreadable max delay dev ratio value at line %d", line_number);
|
||||
break;
|
||||
case CPS_BadMaxdelayratio:
|
||||
LOG(LOGS_WARN, LOGF_Configure, "Unreadable max delay ratio value at line %d", line_number);
|
||||
break;
|
||||
|
|
25
ntp_core.c
25
ntp_core.c
|
@ -119,6 +119,8 @@ struct NCR_Instance_Record {
|
|||
min_delay_in_register that we can
|
||||
tolerate. */
|
||||
|
||||
double max_delay_dev_ratio; /* Maximum ratio of increase in delay / stddev */
|
||||
|
||||
int do_auth; /* Flag indicating whether we
|
||||
authenticate packets we send to
|
||||
this machine (if it's serving us or
|
||||
|
@ -213,7 +215,7 @@ void
|
|||
NCR_Initialise(void)
|
||||
{
|
||||
logfileid = CNF_GetLogMeasurements() ? LOG_FileOpen("measurements",
|
||||
" Date (UTC) Time IP Address L St 1234 ab 5678 LP RP Score Offset Peer del. Peer disp. Root del. Root disp.")
|
||||
" Date (UTC) Time IP Address L St 1234 abc 5678 LP RP Score Offset Peer del. Peer disp. Root del. Root disp.")
|
||||
: -1;
|
||||
|
||||
access_auth_table = ADF_CreateTable();
|
||||
|
@ -284,6 +286,7 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
|
|||
|
||||
result->max_delay = params->max_delay;
|
||||
result->max_delay_ratio = params->max_delay_ratio;
|
||||
result->max_delay_dev_ratio = params->max_delay_dev_ratio;
|
||||
|
||||
result->tx_count = 0;
|
||||
|
||||
|
@ -777,7 +780,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
|||
|
||||
int test1, test2, test3, test4, test5, test6, test7, test8;
|
||||
|
||||
int test4a, test4b;
|
||||
int test4a, test4b, test4c;
|
||||
|
||||
/* In the words of section 3.4.4 of RFC1305, valid_data means
|
||||
that the NTP protocol association with the peer/server is
|
||||
|
@ -941,6 +944,18 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
|||
test4b = 1; /* Success */
|
||||
}
|
||||
|
||||
/* Test 4c (additional to RFC1305) requires that the ratio of the
|
||||
increase in delay from the minimum one in the stats data register to
|
||||
the standard deviation of the offsets in the register is less than an
|
||||
administrator-defined value or the difference between measured offset
|
||||
and predicted offset is larger than the increase in delay */
|
||||
if (!SRC_IsGoodSample(inst->source, -theta, delta, inst->max_delay_dev_ratio,
|
||||
LCL_GetMaxClockError(), &sample_time)) {
|
||||
test4c = 0; /* Failed */
|
||||
} else {
|
||||
test4c = 1; /* Success */
|
||||
}
|
||||
|
||||
/* Test 5 relates to authentication. */
|
||||
if (inst->do_auth) {
|
||||
if (do_auth) {
|
||||
|
@ -1011,7 +1026,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
|||
|
||||
valid_kod = test1 && test2 && test5;
|
||||
|
||||
valid_data = test1 && test2 && test3 && test4 && test4a && test4b;
|
||||
valid_data = test1 && test2 && test3 && test4 && test4a && test4b && test4c;
|
||||
valid_header = test5 && test6 && test7 && test8;
|
||||
|
||||
root_delay = pkt_root_delay + delta;
|
||||
|
@ -1240,13 +1255,13 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
|||
|
||||
/* Do measurement logging */
|
||||
if (logfileid != -1) {
|
||||
LOG_FileWrite(logfileid, "%s %-15s %1c %2d %1d%1d%1d%1d %1d%1d %1d%1d%1d%1d %2d %2d %4.2f %10.3e %10.3e %10.3e %10.3e %10.3e",
|
||||
LOG_FileWrite(logfileid, "%s %-15s %1c %2d %1d%1d%1d%1d %1d%1d%1d %1d%1d%1d%1d %2d %2d %4.2f %10.3e %10.3e %10.3e %10.3e %10.3e",
|
||||
UTI_TimeToLogForm(sample_time.tv_sec),
|
||||
UTI_IPToString(&inst->remote_addr.ip_addr),
|
||||
sync_stats[pkt_leap],
|
||||
message->stratum,
|
||||
test1, test2, test3, test4,
|
||||
test4a, test4b,
|
||||
test4a, test4b, test4c,
|
||||
test5, test6, test7, test8,
|
||||
inst->local_poll, inst->remote_poll,
|
||||
inst->poll_score,
|
||||
|
|
10
sources.c
10
sources.c
|
@ -794,6 +794,16 @@ SRC_MinRoundTripDelay(SRC_Instance inst)
|
|||
return SST_MinRoundTripDelay(inst->stats);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
SRC_IsGoodSample(SRC_Instance inst, double offset, double delay,
|
||||
double max_delay_dev_ratio, double clock_error, struct timeval *when)
|
||||
{
|
||||
return SST_IsGoodSample(inst->stats, offset, delay, max_delay_dev_ratio,
|
||||
clock_error, when);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* This routine is registered as a callback with the local clock
|
||||
module, to be called whenever the local clock changes frequency or
|
||||
|
|
|
@ -145,6 +145,10 @@ extern double SRC_PredictOffset(SRC_Instance inst, struct timeval *when);
|
|||
currently held in the register */
|
||||
extern double SRC_MinRoundTripDelay(SRC_Instance inst);
|
||||
|
||||
/* This routine determines if a new sample is good enough that it should be
|
||||
accumulated */
|
||||
extern int SRC_IsGoodSample(SRC_Instance inst, double offset, double delay, double max_delay_dev_ratio, double clock_error, struct timeval *when);
|
||||
|
||||
extern void SRC_DumpSources(void);
|
||||
|
||||
extern void SRC_ReloadSources(void);
|
||||
|
|
|
@ -693,6 +693,45 @@ SST_MinRoundTripDelay(SST_Stats inst)
|
|||
return inst->peer_delays[inst->min_delay_sample];
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
SST_IsGoodSample(SST_Stats inst, double offset, double delay,
|
||||
double max_delay_dev_ratio, double clock_error, struct timeval *when)
|
||||
{
|
||||
double elapsed, allowed_increase, delay_increase;
|
||||
|
||||
if (inst->n_samples < 3)
|
||||
return 1;
|
||||
|
||||
UTI_DiffTimevalsToDouble(&elapsed, when, &inst->offset_time);
|
||||
|
||||
/* Require that the ratio of the increase in delay from the minimum to the
|
||||
standard deviation is less than max_delay_dev_ratio. In the allowed
|
||||
increase in delay include also skew and clock_error. */
|
||||
|
||||
allowed_increase = sqrt(inst->variance) * max_delay_dev_ratio +
|
||||
elapsed * (inst->skew + clock_error);
|
||||
delay_increase = (delay - SST_MinRoundTripDelay(inst)) / 2.0;
|
||||
|
||||
if (delay_increase < allowed_increase)
|
||||
return 1;
|
||||
|
||||
offset -= inst->estimated_offset + elapsed * inst->estimated_frequency;
|
||||
|
||||
/* Before we decide to drop the sample, make sure the difference between
|
||||
measured offset and predicted offset is not significantly larger than
|
||||
the increase in delay */
|
||||
if (fabs(offset) - delay_increase > allowed_increase)
|
||||
return 1;
|
||||
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_SourceStats, "bad sample: offset=%f delay=%f incr_delay=%f allowed=%f", offset, delay, allowed_increase, delay_increase);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* This is used to save the register to a file, so that we can reload
|
||||
it after restarting the daemon */
|
||||
|
|
|
@ -137,6 +137,11 @@ extern double SST_PredictOffset(SST_Stats inst, struct timeval *when);
|
|||
/* Find the minimum round trip delay in the register */
|
||||
extern double SST_MinRoundTripDelay(SST_Stats inst);
|
||||
|
||||
/* This routine determines if a new sample is good enough that it should be
|
||||
accumulated */
|
||||
extern int SST_IsGoodSample(SST_Stats inst, double offset, double delay,
|
||||
double max_delay_dev_ratio, double clock_error, struct timeval *when);
|
||||
|
||||
extern void SST_SaveToFile(SST_Stats inst, FILE *out);
|
||||
|
||||
extern int SST_LoadFromFile(SST_Stats inst, FILE *in);
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef struct {
|
|||
unsigned long authkey;
|
||||
double max_delay;
|
||||
double max_delay_ratio;
|
||||
double max_delay_dev_ratio;
|
||||
SRC_SelectOption sel_option;
|
||||
} SourceParameters;
|
||||
|
||||
|
@ -54,6 +55,7 @@ typedef struct {
|
|||
#define SRC_DEFAULT_PRESEND_MINPOLL 0
|
||||
#define SRC_DEFAULT_MAXDELAY 16.0
|
||||
#define SRC_DEFAULT_MAXDELAYRATIO 16384.0
|
||||
#define SRC_DEFAULT_MAXDELAYDEVRATIO 10.0
|
||||
#define SRC_DEFAULT_MINSTRATUM 0
|
||||
#define SRC_DEFAULT_POLLTARGET 6
|
||||
#define INACTIVE_AUTHKEY 0UL
|
||||
|
|
Loading…
Reference in a new issue