Base poll adjustment on number of sourcestats samples
Instead of following skew changes, adjust polling interval so that the number of measurements used in the regression algorithm remains close to a target value. It can be configured with a new polltarget option (6 by default).
This commit is contained in:
parent
d9596334c3
commit
7a6ee1d729
12 changed files with 88 additions and 50 deletions
10
chrony.texi
10
chrony.texi
|
@ -1861,8 +1861,8 @@ Local poll [10]
|
|||
Remote poll [10]
|
||||
@item
|
||||
`Score' (an internal score within each polling level used to decide when
|
||||
to increase or decrease the polling level. This is adjusted based on
|
||||
changes to the variance of the measurements obtained from the source). [1]
|
||||
to increase or decrease the polling level. This is adjusted based on number
|
||||
of measurements currently being used for the regression algorithm). [1.0]
|
||||
@item
|
||||
The estimated local clock error (`theta' in RFC1305). Positive indicates that the local clock is slow. [-4.966e-03].
|
||||
@item
|
||||
|
@ -2629,6 +2629,12 @@ selecting that source. This is useful with low stratum sources that are known
|
|||
to be unrealiable or inaccurate and which should be used only when other
|
||||
sources are unreachable.
|
||||
|
||||
@item polltarget
|
||||
Target number of measurements to use for the regression algorithm which
|
||||
@code{chronyd} will try to maintain by adjusting polling interval between
|
||||
@code{minpoll} and @code{maxpoll}. A higher target makes @code{chronyd} prefer
|
||||
shorter polling intervals. The default is 6 and a useful range is 6 to 60.
|
||||
|
||||
@item prefer
|
||||
Prefer this source over sources without prefer option.
|
||||
|
||||
|
|
8
client.c
8
client.c
|
@ -936,6 +936,11 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
|
|||
break;
|
||||
}
|
||||
|
||||
if (data.params.poll_target != SRC_DEFAULT_POLLTARGET) {
|
||||
fprintf(stderr, "Option polltarget 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);
|
||||
|
@ -983,6 +988,9 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
|
|||
case CPS_BadMinstratum:
|
||||
fprintf(stderr, "Unreadable minstratum value\n");
|
||||
break;
|
||||
case CPS_BadPolltarget:
|
||||
fprintf(stderr, "Unreadable polltarget value\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
1
cmdmon.c
1
cmdmon.c
|
@ -1251,6 +1251,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;
|
||||
|
||||
status = NSR_AddSource(&rem_addr, type, ¶ms);
|
||||
switch (status) {
|
||||
|
|
10
cmdparse.c
10
cmdparse.c
|
@ -60,6 +60,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
|
|||
src->params.auto_offline = 0;
|
||||
src->params.iburst = 0;
|
||||
src->params.min_stratum = SRC_DEFAULT_MINSTRATUM;
|
||||
src->params.poll_target = SRC_DEFAULT_POLLTARGET;
|
||||
src->params.sel_option = SRC_SelectNormal;
|
||||
|
||||
result = CPS_Success;
|
||||
|
@ -165,6 +166,15 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
|
|||
line += n;
|
||||
}
|
||||
|
||||
} else if (!strncasecmp(cmd, "polltarget", 10)) {
|
||||
if (sscanf(line, "%d%n", &src->params.poll_target, &n) != 1) {
|
||||
result = CPS_BadPolltarget;
|
||||
ok = 0;
|
||||
done = 1;
|
||||
} else {
|
||||
line += n;
|
||||
}
|
||||
|
||||
} else if (!strncasecmp(cmd, "noselect", 8)) {
|
||||
src->params.sel_option = SRC_SelectNoselect;
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ typedef enum {
|
|||
CPS_BadMaxdelayratio,
|
||||
CPS_BadMaxdelay,
|
||||
CPS_BadKey,
|
||||
CPS_BadMinstratum
|
||||
CPS_BadMinstratum,
|
||||
CPS_BadPolltarget
|
||||
} CPS_Status;
|
||||
|
||||
typedef struct {
|
||||
|
|
3
conf.c
3
conf.c
|
@ -397,6 +397,9 @@ parse_source(const char *line, NTP_Source_Type type)
|
|||
case CPS_BadMinstratum:
|
||||
LOG(LOGS_WARN, LOGF_Configure, "Unreadable minstratum value at line %d", line_number);
|
||||
break;
|
||||
case CPS_BadPolltarget:
|
||||
LOG(LOGS_WARN, LOGF_Configure, "Unreadable polltarget value at line %d", line_number);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
81
ntp_core.c
81
ntp_core.c
|
@ -55,10 +55,6 @@ static LOG_FileID logfileid;
|
|||
/* Day number of 1 Jan 1970 */
|
||||
#define MJD_1970 40587
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#define ZONE_WIDTH 4
|
||||
|
||||
/* ================================================== */
|
||||
/* Enumeration used for remembering the operating mode of one of the
|
||||
sources */
|
||||
|
@ -110,6 +106,10 @@ struct NCR_Instance_Record {
|
|||
int min_stratum; /* Increase stratum in received packets to the
|
||||
minimum */
|
||||
|
||||
int poll_target; /* Target number of sourcestats samples */
|
||||
|
||||
double poll_score; /* Score of current local poll */
|
||||
|
||||
double max_delay; /* Maximum round-trip delay to the
|
||||
peer that we can tolerate and still
|
||||
use the sample for generating
|
||||
|
@ -163,8 +163,6 @@ struct NCR_Instance_Record {
|
|||
|
||||
SRC_Instance source;
|
||||
|
||||
int score;
|
||||
|
||||
int burst_good_samples_to_go;
|
||||
int burst_total_samples_to_go;
|
||||
|
||||
|
@ -215,7 +213,7 @@ void
|
|||
NCR_Initialise(void)
|
||||
{
|
||||
logfileid = CNF_GetLogMeasurements() ? LOG_FileOpen("measurements",
|
||||
" Date (UTC) Time IP Address L St 1234 ab 5678 LP RP SC Offset Peer del. Peer disp. Root del. Root disp.")
|
||||
" Date (UTC) Time IP Address L St 1234 ab 5678 LP RP Score Offset Peer del. Peer disp. Root del. Root disp.")
|
||||
: -1;
|
||||
|
||||
access_auth_table = ADF_CreateTable();
|
||||
|
@ -292,7 +290,8 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
|
|||
result->remote_orig.hi = 0;
|
||||
result->remote_orig.lo = 0;
|
||||
|
||||
result->score = 0;
|
||||
result->poll_target = params->poll_target;
|
||||
result->poll_score = 0.0;
|
||||
|
||||
if (params->online) {
|
||||
start_initial_timeout(result);
|
||||
|
@ -448,29 +447,28 @@ check_packet_auth(NTP_Packet *pkt, unsigned long keyid)
|
|||
/* ================================================== */
|
||||
|
||||
static void
|
||||
normalise_score(NCR_Instance inst)
|
||||
adjust_poll(NCR_Instance inst, double adj)
|
||||
{
|
||||
inst->poll_score += adj;
|
||||
|
||||
while (inst->score >= ZONE_WIDTH) {
|
||||
++inst->local_poll;
|
||||
inst->score -= ZONE_WIDTH;
|
||||
if (inst->poll_score >= 1.0) {
|
||||
inst->local_poll += (int)inst->poll_score;
|
||||
inst->poll_score -= (int)inst->poll_score;
|
||||
}
|
||||
while (inst->score < 0) {
|
||||
if (inst->local_poll > 0) {
|
||||
--inst->local_poll;
|
||||
}
|
||||
inst->score += ZONE_WIDTH;
|
||||
|
||||
if (inst->poll_score < 0.0) {
|
||||
inst->local_poll += (int)(inst->poll_score - 1.0);
|
||||
inst->poll_score -= (int)(inst->poll_score - 1.0);
|
||||
}
|
||||
|
||||
/* Clamp polling interval to defined range */
|
||||
if (inst->local_poll < inst->minpoll) {
|
||||
inst->local_poll = inst->minpoll;
|
||||
inst->score = 0;
|
||||
inst->poll_score = 0;
|
||||
} else if (inst->local_poll > inst->maxpoll) {
|
||||
inst->local_poll = inst->maxpoll;
|
||||
inst->score = ZONE_WIDTH - 1;
|
||||
inst->poll_score = 1.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -652,13 +650,11 @@ transmit_timeout(void *arg)
|
|||
if (SRC_IsSyncPeer(inst->source)) {
|
||||
if (inst->tx_count >= 2) {
|
||||
/* Implies we have missed at least one transmission */
|
||||
inst->score -= 3;
|
||||
normalise_score(inst);
|
||||
adjust_poll(inst, -0.75);
|
||||
}
|
||||
} else {
|
||||
if (inst->tx_count >= 2) {
|
||||
inst->score += 1;
|
||||
normalise_score(inst);
|
||||
adjust_poll(inst, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -810,7 +806,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
|||
int poll_to_use;
|
||||
double delay_time = 0;
|
||||
int requeue_transmit = 0;
|
||||
int delta_score;
|
||||
double poll_adj;
|
||||
|
||||
/* ==================== */
|
||||
|
||||
|
@ -1089,31 +1085,22 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
|||
temp>>=1;
|
||||
} while (temp);
|
||||
|
||||
inst->local_poll -= shift;
|
||||
inst->score = 0;
|
||||
poll_adj = -shift - inst->poll_score + 0.5;
|
||||
|
||||
} else {
|
||||
int samples = SRC_Samples(inst->source);
|
||||
|
||||
switch (SRC_LastSkewChange(inst->source)) {
|
||||
case SRC_Skew_Decrease:
|
||||
delta_score = 1;
|
||||
break;
|
||||
case SRC_Skew_Nochange:
|
||||
delta_score = 0;
|
||||
break;
|
||||
case SRC_Skew_Increase:
|
||||
delta_score = -2;
|
||||
break;
|
||||
default: /* Should not happen! */
|
||||
delta_score = 0;
|
||||
break;
|
||||
}
|
||||
/* Adjust polling interval so that the number of sourcestats samples
|
||||
remains close to the target value */
|
||||
poll_adj = ((double)samples / inst->poll_target - 1.0) / inst->poll_target;
|
||||
|
||||
inst->score += delta_score;
|
||||
/* Use higher gain when decreasing the interval */
|
||||
if (samples < inst->poll_target) {
|
||||
poll_adj *= 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
normalise_score(inst);
|
||||
|
||||
adjust_poll(inst, poll_adj);
|
||||
}
|
||||
|
||||
/* Reduce polling rate if KoD RATE was received */
|
||||
|
@ -1253,7 +1240,7 @@ 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 %2d %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 %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],
|
||||
|
@ -1262,7 +1249,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
|||
test4a, test4b,
|
||||
test5, test6, test7, test8,
|
||||
inst->local_poll, inst->remote_poll,
|
||||
(inst->score),
|
||||
inst->poll_score,
|
||||
theta, delta, epsilon,
|
||||
pkt_root_delay, pkt_root_dispersion);
|
||||
}
|
||||
|
@ -1668,7 +1655,7 @@ NCR_TakeSourceOnline(NCR_Instance inst)
|
|||
/* We are not already actively polling it */
|
||||
LOG(LOGS_INFO, LOGF_NtpCore, "Source %s online", UTI_IPToString(&inst->remote_addr.ip_addr));
|
||||
inst->local_poll = inst->minpoll;
|
||||
inst->score = (ZONE_WIDTH >> 1);
|
||||
inst->poll_score = 0.5;
|
||||
inst->opmode = MD_ONLINE;
|
||||
start_initial_timeout(inst);
|
||||
}
|
||||
|
|
|
@ -1027,3 +1027,11 @@ SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst)
|
|||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
SRC_Samples(SRC_Instance inst)
|
||||
{
|
||||
return SST_Samples(inst->stats);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
|
|
@ -165,5 +165,7 @@ typedef enum {
|
|||
|
||||
extern SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst);
|
||||
|
||||
extern int SRC_Samples(SRC_Instance inst);
|
||||
|
||||
#endif /* GOT_SOURCES_H */
|
||||
|
||||
|
|
|
@ -789,6 +789,14 @@ SST_Skew_Direction SST_LastSkewChange(SST_Stats inst)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
SST_Samples(SST_Stats inst)
|
||||
{
|
||||
return inst->n_samples;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct timeval *now)
|
||||
{
|
||||
|
|
|
@ -153,5 +153,7 @@ typedef enum {
|
|||
|
||||
extern SST_Skew_Direction SST_LastSkewChange(SST_Stats inst);
|
||||
|
||||
extern int SST_Samples(SST_Stats inst);
|
||||
|
||||
#endif /* GOT_SOURCESTATS_H */
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef struct {
|
|||
int presend_minpoll;
|
||||
int iburst;
|
||||
int min_stratum;
|
||||
int poll_target;
|
||||
unsigned long authkey;
|
||||
double max_delay;
|
||||
double max_delay_ratio;
|
||||
|
@ -54,6 +55,7 @@ typedef struct {
|
|||
#define SRC_DEFAULT_MAXDELAY 16.0
|
||||
#define SRC_DEFAULT_MAXDELAYRATIO 16384.0
|
||||
#define SRC_DEFAULT_MINSTRATUM 0
|
||||
#define SRC_DEFAULT_POLLTARGET 6
|
||||
#define INACTIVE_AUTHKEY 0UL
|
||||
|
||||
#endif /* GOT_SRCPARAMS_H */
|
||||
|
|
Loading…
Reference in a new issue