sources: allow setting minsamples and maxsamples for each source

The minsamples and maxsamples directives now set the default value,
which can be overriden for individual sources in the server/peer/pool
and refclock directives.
This commit is contained in:
Miroslav Lichvar 2014-12-01 18:35:35 +01:00
parent 42dd5caa1b
commit 6688f40325
13 changed files with 108 additions and 22 deletions

View file

@ -2375,9 +2375,11 @@ crystal oscillator.
@c {{{ maxsamples
@node maxsamples directive
@subsection maxsamples
The @code{maxsamples} directive sets the maximum number of samples
@code{chronyd} should keep for each source. The default is 0, which
disables the configurable limit, and the useful range is 4 to 64.
The @code{maxsamples} directive sets the default maximum number of samples
@code{chronyd} should keep for each source. This setting can be overriden for
individual sources in the @code{server} and @code{refclock} directives
(@pxref{server directive}, @pxref{refclock directive}). The default value is
0, which disables the configurable limit. The useful range is 4 to 64.
The syntax is
@ -2439,9 +2441,11 @@ the new master estimate.
@c {{{ minsamples
@node minsamples directive
@subsection minsamples
The @code{minsamples} directive sets the minimum number of samples
@code{chronyd} should try to keep for each source. The default is 0 and the
useful range is 4 to 64.
The @code{minsamples} directive sets the default minimum number of samples
@code{chronyd} should keep for each source. This setting can be overriden for
individual sources in the @code{server} and @code{refclock} directives
(@pxref{server directive}, @pxref{refclock directive}). The default value is
0. The useful range is 4 to 64.
The syntax is
@ -2669,6 +2673,12 @@ Prefer this source over sources without prefer option.
@item noselect
Never select this source. This is useful for monitoring or with sources
which are not very accurate, but are locked with a PPS refclock.
@item minsamples
Set the minimum number of samples kept for this source. This overrides the
@code{minsamples} directive (@pxref{minsamples directive}).
@item maxsamples
Set the maximum number of samples kept for this source. This overrides the
@code{maxsamples} directive (@pxref{maxsamples directive}).
@end table
@c }}}
@ -2956,6 +2966,14 @@ Prefer this source over sources without prefer option.
@item noselect
Never select this source. This is particularly useful for monitoring.
@item minsamples
Set the minimum number of samples kept for this source. This overrides the
@code{minsamples} directive (@pxref{minsamples directive}).
@item maxsamples
Set the maximum number of samples kept for this source. This overrides the
@code{maxsamples} directive (@pxref{maxsamples directive}).
@end table
@c }}}
@c {{{ stratumweight

View file

@ -965,6 +965,16 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
break;
}
if (data.params.min_samples != SRC_DEFAULT_MINSAMPLES) {
fprintf(stderr, "Option minsamples not supported\n");
break;
}
if (data.params.max_samples != SRC_DEFAULT_MAXSAMPLES) {
fprintf(stderr, "Option maxsamples not supported\n");
break;
}
msg->data.ntp_source.port = htonl((unsigned long) data.port);
UTI_IPHostToNetwork(&ip_addr, &msg->data.ntp_source.ip_addr);
msg->data.ntp_source.minpoll = htonl(data.params.minpoll);
@ -1024,6 +1034,12 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
case CPS_BadMaxsources:
fprintf(stderr, "Unreadable maxsources value\n");
break;
case CPS_BadMinsamples:
fprintf(stderr, "Unreadable minsamples value\n");
break;
case CPS_BadMaxsamples:
fprintf(stderr, "Unreadable maxsamples value\n");
break;
}
return result;

View file

@ -61,6 +61,8 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
src->params.poll_target = SRC_DEFAULT_POLLTARGET;
src->params.version = NTP_VERSION;
src->params.max_sources = SRC_DEFAULT_MAXSOURCES;
src->params.min_samples = SRC_DEFAULT_MINSAMPLES;
src->params.max_samples = SRC_DEFAULT_MAXSAMPLES;
src->params.sel_option = SRC_SelectNormal;
result = CPS_Success;
@ -184,6 +186,22 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
line += n;
}
} else if (!strcasecmp(cmd, "minsamples")) {
if (sscanf(line, "%d%n", &src->params.min_samples, &n) != 1) {
result = CPS_BadMinsamples;
done = 1;
} else {
line += n;
}
} else if (!strcasecmp(cmd, "maxsamples")) {
if (sscanf(line, "%d%n", &src->params.max_samples, &n) != 1) {
result = CPS_BadMaxsamples;
done = 1;
} else {
line += n;
}
} else {
result = CPS_BadOption;
done = 1;

View file

@ -46,6 +46,8 @@ typedef enum {
CPS_BadPolltarget,
CPS_BadVersion,
CPS_BadMaxsources,
CPS_BadMinsamples,
CPS_BadMaxsamples,
} CPS_Status;
typedef struct {

18
conf.c
View file

@ -635,6 +635,12 @@ parse_source(char *line, NTP_Source_Type type, int pool)
case CPS_BadMaxsources:
other_parse_error("Unreadable maxsources");
break;
case CPS_BadMinsamples:
other_parse_error("Unreadable minsamples");
break;
case CPS_BadMaxsamples:
other_parse_error("Unreadable maxsamples");
break;
}
}
@ -667,7 +673,7 @@ parse_pool(char *line)
static void
parse_refclock(char *line)
{
int n, poll, dpoll, filter_length, pps_rate;
int n, poll, dpoll, filter_length, pps_rate, min_samples, max_samples;
uint32_t ref_id, lock_ref_id;
double offset, delay, precision, max_dispersion;
char *p, *cmd, *name, *param;
@ -679,6 +685,8 @@ parse_refclock(char *line)
dpoll = 0;
filter_length = 64;
pps_rate = 0;
min_samples = SRC_DEFAULT_MINSAMPLES;
max_samples = SRC_DEFAULT_MAXSAMPLES;
offset = 0.0;
delay = 1e-9;
precision = 0.0;
@ -732,6 +740,12 @@ parse_refclock(char *line)
} else if (!strcasecmp(cmd, "rate")) {
if (sscanf(line, "%d%n", &pps_rate, &n) != 1)
break;
} else if (!strcasecmp(cmd, "minsamples")) {
if (sscanf(line, "%d%n", &min_samples, &n) != 1)
break;
} else if (!strcasecmp(cmd, "maxsamples")) {
if (sscanf(line, "%d%n", &max_samples, &n) != 1)
break;
} else if (!strcasecmp(cmd, "offset")) {
if (sscanf(line, "%lf%n", &offset, &n) != 1)
break;
@ -768,6 +782,8 @@ parse_refclock(char *line)
refclock->poll = poll;
refclock->filter_length = filter_length;
refclock->pps_rate = pps_rate;
refclock->min_samples = min_samples;
refclock->max_samples = max_samples;
refclock->offset = offset;
refclock->delay = delay;
refclock->precision = precision;

View file

@ -461,7 +461,10 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
}
/* Create a source instance for this NTP source */
result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), SRC_NTP, params->sel_option, &result->remote_addr.ip_addr);
result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr),
SRC_NTP, params->sel_option,
&result->remote_addr.ip_addr,
params->min_samples, params->max_samples);
result->timer_running = 0;
result->timeout_id = 0;

View file

@ -260,7 +260,8 @@ RCL_AddRefclock(RefclockParameters *params)
filter_init(&inst->filter, params->filter_length, params->max_dispersion);
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_option, NULL);
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_option, NULL,
params->min_samples, params->max_samples);
DEBUG_LOG(LOGF_Refclock, "refclock %s refid=%s poll=%d dpoll=%d filter=%d",
params->driver_name, UTI_RefidToString(inst->ref_id),

View file

@ -38,6 +38,8 @@ typedef struct {
int poll;
int filter_length;
int pps_rate;
int min_samples;
int max_samples;
uint32_t ref_id;
uint32_t lock_ref_id;
double offset;

View file

@ -207,14 +207,19 @@ void SRC_Finalise(void)
/* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */
SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, SRC_SelectOption sel_option, IPAddr *addr)
SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, SRC_SelectOption sel_option, IPAddr *addr, int min_samples, int max_samples)
{
SRC_Instance result;
assert(initialised);
if (min_samples == SRC_DEFAULT_MINSAMPLES)
min_samples = CNF_GetMinSamples();
if (max_samples == SRC_DEFAULT_MAXSAMPLES)
max_samples = CNF_GetMaxSamples();
result = MallocNew(struct SRC_Instance_Record);
result->stats = SST_CreateInstance(ref_id, addr);
result->stats = SST_CreateInstance(ref_id, addr, min_samples, max_samples);
if (n_sources == max_n_sources) {
/* Reallocate memory */

View file

@ -65,7 +65,7 @@ typedef enum {
/* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */
extern SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, SRC_SelectOption sel_option, IPAddr *addr);
extern SRC_Instance SRC_CreateNewInstance(uint32_t ref_id, SRC_Type type, SRC_SelectOption sel_option, IPAddr *addr, int min_samples, int max_samples);
/* Function to get rid of a source when it is being unconfigured.
This may cause the current reference source to be reselected, if this

View file

@ -43,10 +43,6 @@
to store per source */
#define MAX_SAMPLES 64
/* User defined maximum and minimum number of samples */
int max_samples;
int min_samples;
/* This is the assumed worst case bound on an unknown frequency,
2000ppm, which would be pretty bad */
#define WORST_CASE_FREQ_BOUND (2000.0/1.0e6)
@ -68,6 +64,10 @@ struct SST_Stats_Record {
uint32_t refid;
IPAddr *ip_addr;
/* User defined minimum and maximum number of samples */
int min_samples;
int max_samples;
/* Number of samples currently stored. The samples are stored in circular
buffer. */
int n_samples;
@ -163,8 +163,6 @@ SST_Initialise(void)
logfileid = CNF_GetLogStatistics() ? LOG_FileOpen("statistics",
" Date (UTC) Time IP Address Std dev'n Est offset Offset sd Diff freq Est skew Stress Ns Bs Nr")
: -1;
max_samples = CNF_GetMaxSamples();
min_samples = CNF_GetMinSamples();
}
/* ================================================== */
@ -178,11 +176,14 @@ SST_Finalise(void)
/* This function creates a new instance of the statistics handler */
SST_Stats
SST_CreateInstance(uint32_t refid, IPAddr *addr)
SST_CreateInstance(uint32_t refid, IPAddr *addr, int min_samples, int max_samples)
{
SST_Stats inst;
inst = MallocNew(struct SST_Stats_Record);
inst->min_samples = min_samples;
inst->max_samples = max_samples;
SST_SetRefid(inst, refid, addr);
SST_ResetInstance(inst);
@ -262,7 +263,7 @@ SST_AccumulateSample(SST_Stats inst, struct timeval *sample_time,
/* Make room for the new sample */
if (inst->n_samples > 0 &&
(inst->n_samples == MAX_SAMPLES || inst->n_samples == max_samples)) {
(inst->n_samples == MAX_SAMPLES || inst->n_samples == inst->max_samples)) {
prune_register(inst, 1);
}
@ -447,7 +448,7 @@ SST_DoNewRegression(SST_Stats inst)
inst->regression_ok = RGR_FindBestRegression(times_back + inst->runs_samples,
offsets + inst->runs_samples, weights,
inst->n_samples, inst->runs_samples,
min_samples,
inst->min_samples,
&est_intercept, &est_slope, &est_var,
&est_intercept_sd, &est_slope_sd,
&best_start, &nruns, &degrees_of_freedom);

View file

@ -38,7 +38,7 @@ extern void SST_Initialise(void);
extern void SST_Finalise(void);
/* This function creates a new instance of the statistics handler */
extern SST_Stats SST_CreateInstance(uint32_t refid, IPAddr *addr);
extern SST_Stats SST_CreateInstance(uint32_t refid, IPAddr *addr, int min_samples, int max_samples);
/* This function deletes an instance of the statistics handler. */
extern void SST_DeleteInstance(SST_Stats inst);

View file

@ -40,6 +40,8 @@ typedef struct {
int poll_target;
int version;
int max_sources;
int min_samples;
int max_samples;
uint32_t authkey;
double max_delay;
double max_delay_ratio;
@ -57,6 +59,8 @@ typedef struct {
#define SRC_DEFAULT_MINSTRATUM 0
#define SRC_DEFAULT_POLLTARGET 6
#define SRC_DEFAULT_MAXSOURCES 4
#define SRC_DEFAULT_MINSAMPLES (-1)
#define SRC_DEFAULT_MAXSAMPLES (-1)
#define INACTIVE_AUTHKEY 0
#endif /* GOT_SRCPARAMS_H */