From: Miroslav Lichvar Date: Wed, 13 Oct 2010 14:49:28 +0000 (+0200) Subject: Base poll adjustment on number of sourcestats samples X-Git-Tag: 1.25-pre1~45 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7a6ee1d;p=thirdparty%2Fchrony.git 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). --- diff --git a/chrony.texi b/chrony.texi index beb6b40f..f86a0ac0 100644 --- a/chrony.texi +++ b/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. diff --git a/client.c b/client.c index 2b7164e9..c31564d2 100644 --- a/client.c +++ b/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; diff --git a/cmdmon.c b/cmdmon.c index 1a1c10ea..3b9fe193 100644 --- a/cmdmon.c +++ b/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) { diff --git a/cmdparse.c b/cmdparse.c index dca477f9..be459894 100644 --- a/cmdparse.c +++ b/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; diff --git a/cmdparse.h b/cmdparse.h index 9f4d4ae5..a6353bd5 100644 --- a/cmdparse.h +++ b/cmdparse.h @@ -45,7 +45,8 @@ typedef enum { CPS_BadMaxdelayratio, CPS_BadMaxdelay, CPS_BadKey, - CPS_BadMinstratum + CPS_BadMinstratum, + CPS_BadPolltarget } CPS_Status; typedef struct { diff --git a/conf.c b/conf.c index 552a5fd0..5bfd3264 100644 --- a/conf.c +++ b/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; diff --git a/ntp_core.c b/ntp_core.c index 7f8d3ca0..62148cb8 100644 --- a/ntp_core.c +++ b/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); } diff --git a/sources.c b/sources.c index a0198901..38706cac 100644 --- a/sources.c +++ b/sources.c @@ -1027,3 +1027,11 @@ SRC_Skew_Direction SRC_LastSkewChange(SRC_Instance inst) } /* ================================================== */ + +int +SRC_Samples(SRC_Instance inst) +{ + return SST_Samples(inst->stats); +} + +/* ================================================== */ diff --git a/sources.h b/sources.h index aff800a9..d89ce597 100644 --- a/sources.h +++ b/sources.h @@ -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 */ diff --git a/sourcestats.c b/sourcestats.c index bcd818e1..652421fc 100644 --- a/sourcestats.c +++ b/sourcestats.c @@ -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) { diff --git a/sourcestats.h b/sourcestats.h index c48af7b7..e47287f7 100644 --- a/sourcestats.h +++ b/sourcestats.h @@ -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 */ diff --git a/srcparams.h b/srcparams.h index 9db3806a..58395cb4 100644 --- a/srcparams.h +++ b/srcparams.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 */