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:
parent
42dd5caa1b
commit
6688f40325
13 changed files with 108 additions and 22 deletions
|
@ -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
|
||||
|
|
16
client.c
16
client.c
|
@ -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;
|
||||
|
|
18
cmdparse.c
18
cmdparse.c
|
@ -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;
|
||||
|
|
|
@ -46,6 +46,8 @@ typedef enum {
|
|||
CPS_BadPolltarget,
|
||||
CPS_BadVersion,
|
||||
CPS_BadMaxsources,
|
||||
CPS_BadMinsamples,
|
||||
CPS_BadMaxsamples,
|
||||
} CPS_Status;
|
||||
|
||||
typedef struct {
|
||||
|
|
18
conf.c
18
conf.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, °rees_of_freedom);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue