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:
Miroslav Lichvar 2010-10-13 16:49:28 +02:00
parent d9596334c3
commit 7a6ee1d729
12 changed files with 88 additions and 50 deletions

View file

@ -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.

View file

@ -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;

View file

@ -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, &params);
switch (status) {

View file

@ -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;

View file

@ -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
View file

@ -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;

View file

@ -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);
}

View file

@ -1027,3 +1027,11 @@ SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst)
}
/* ================================================== */
int
SRC_Samples(SRC_Instance inst)
{
return SST_Samples(inst->stats);
}
/* ================================================== */

View file

@ -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 */

View file

@ -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)
{

View file

@ -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 */

View file

@ -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 */