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
|
@c {{{ maxsamples
|
||||||
@node maxsamples directive
|
@node maxsamples directive
|
||||||
@subsection maxsamples
|
@subsection maxsamples
|
||||||
The @code{maxsamples} directive sets the maximum number of samples
|
The @code{maxsamples} directive sets the default maximum number of samples
|
||||||
@code{chronyd} should keep for each source. The default is 0, which
|
@code{chronyd} should keep for each source. This setting can be overriden for
|
||||||
disables the configurable limit, and the useful range is 4 to 64.
|
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
|
The syntax is
|
||||||
|
|
||||||
|
@ -2439,9 +2441,11 @@ the new master estimate.
|
||||||
@c {{{ minsamples
|
@c {{{ minsamples
|
||||||
@node minsamples directive
|
@node minsamples directive
|
||||||
@subsection minsamples
|
@subsection minsamples
|
||||||
The @code{minsamples} directive sets the minimum number of samples
|
The @code{minsamples} directive sets the default minimum number of samples
|
||||||
@code{chronyd} should try to keep for each source. The default is 0 and the
|
@code{chronyd} should keep for each source. This setting can be overriden for
|
||||||
useful range is 4 to 64.
|
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
|
The syntax is
|
||||||
|
|
||||||
|
@ -2669,6 +2673,12 @@ Prefer this source over sources without prefer option.
|
||||||
@item noselect
|
@item noselect
|
||||||
Never select this source. This is useful for monitoring or with sources
|
Never select this source. This is useful for monitoring or with sources
|
||||||
which are not very accurate, but are locked with a PPS refclock.
|
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
|
@end table
|
||||||
|
|
||||||
@c }}}
|
@c }}}
|
||||||
|
@ -2956,6 +2966,14 @@ Prefer this source over sources without prefer option.
|
||||||
@item noselect
|
@item noselect
|
||||||
Never select this source. This is particularly useful for monitoring.
|
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
|
@end table
|
||||||
@c }}}
|
@c }}}
|
||||||
@c {{{ stratumweight
|
@c {{{ stratumweight
|
||||||
|
|
16
client.c
16
client.c
|
@ -965,6 +965,16 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
|
||||||
break;
|
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);
|
msg->data.ntp_source.port = htonl((unsigned long) data.port);
|
||||||
UTI_IPHostToNetwork(&ip_addr, &msg->data.ntp_source.ip_addr);
|
UTI_IPHostToNetwork(&ip_addr, &msg->data.ntp_source.ip_addr);
|
||||||
msg->data.ntp_source.minpoll = htonl(data.params.minpoll);
|
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:
|
case CPS_BadMaxsources:
|
||||||
fprintf(stderr, "Unreadable maxsources value\n");
|
fprintf(stderr, "Unreadable maxsources value\n");
|
||||||
break;
|
break;
|
||||||
|
case CPS_BadMinsamples:
|
||||||
|
fprintf(stderr, "Unreadable minsamples value\n");
|
||||||
|
break;
|
||||||
|
case CPS_BadMaxsamples:
|
||||||
|
fprintf(stderr, "Unreadable maxsamples value\n");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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.poll_target = SRC_DEFAULT_POLLTARGET;
|
||||||
src->params.version = NTP_VERSION;
|
src->params.version = NTP_VERSION;
|
||||||
src->params.max_sources = SRC_DEFAULT_MAXSOURCES;
|
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;
|
src->params.sel_option = SRC_SelectNormal;
|
||||||
|
|
||||||
result = CPS_Success;
|
result = CPS_Success;
|
||||||
|
@ -184,6 +186,22 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
|
||||||
line += n;
|
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 {
|
} else {
|
||||||
result = CPS_BadOption;
|
result = CPS_BadOption;
|
||||||
done = 1;
|
done = 1;
|
||||||
|
|
|
@ -46,6 +46,8 @@ typedef enum {
|
||||||
CPS_BadPolltarget,
|
CPS_BadPolltarget,
|
||||||
CPS_BadVersion,
|
CPS_BadVersion,
|
||||||
CPS_BadMaxsources,
|
CPS_BadMaxsources,
|
||||||
|
CPS_BadMinsamples,
|
||||||
|
CPS_BadMaxsamples,
|
||||||
} CPS_Status;
|
} CPS_Status;
|
||||||
|
|
||||||
typedef struct {
|
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:
|
case CPS_BadMaxsources:
|
||||||
other_parse_error("Unreadable maxsources");
|
other_parse_error("Unreadable maxsources");
|
||||||
break;
|
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
|
static void
|
||||||
parse_refclock(char *line)
|
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;
|
uint32_t ref_id, lock_ref_id;
|
||||||
double offset, delay, precision, max_dispersion;
|
double offset, delay, precision, max_dispersion;
|
||||||
char *p, *cmd, *name, *param;
|
char *p, *cmd, *name, *param;
|
||||||
|
@ -679,6 +685,8 @@ parse_refclock(char *line)
|
||||||
dpoll = 0;
|
dpoll = 0;
|
||||||
filter_length = 64;
|
filter_length = 64;
|
||||||
pps_rate = 0;
|
pps_rate = 0;
|
||||||
|
min_samples = SRC_DEFAULT_MINSAMPLES;
|
||||||
|
max_samples = SRC_DEFAULT_MAXSAMPLES;
|
||||||
offset = 0.0;
|
offset = 0.0;
|
||||||
delay = 1e-9;
|
delay = 1e-9;
|
||||||
precision = 0.0;
|
precision = 0.0;
|
||||||
|
@ -732,6 +740,12 @@ parse_refclock(char *line)
|
||||||
} else if (!strcasecmp(cmd, "rate")) {
|
} else if (!strcasecmp(cmd, "rate")) {
|
||||||
if (sscanf(line, "%d%n", &pps_rate, &n) != 1)
|
if (sscanf(line, "%d%n", &pps_rate, &n) != 1)
|
||||||
break;
|
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")) {
|
} else if (!strcasecmp(cmd, "offset")) {
|
||||||
if (sscanf(line, "%lf%n", &offset, &n) != 1)
|
if (sscanf(line, "%lf%n", &offset, &n) != 1)
|
||||||
break;
|
break;
|
||||||
|
@ -768,6 +782,8 @@ parse_refclock(char *line)
|
||||||
refclock->poll = poll;
|
refclock->poll = poll;
|
||||||
refclock->filter_length = filter_length;
|
refclock->filter_length = filter_length;
|
||||||
refclock->pps_rate = pps_rate;
|
refclock->pps_rate = pps_rate;
|
||||||
|
refclock->min_samples = min_samples;
|
||||||
|
refclock->max_samples = max_samples;
|
||||||
refclock->offset = offset;
|
refclock->offset = offset;
|
||||||
refclock->delay = delay;
|
refclock->delay = delay;
|
||||||
refclock->precision = precision;
|
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 */
|
/* 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->timer_running = 0;
|
||||||
result->timeout_id = 0;
|
result->timeout_id = 0;
|
||||||
|
|
|
@ -260,7 +260,8 @@ RCL_AddRefclock(RefclockParameters *params)
|
||||||
|
|
||||||
filter_init(&inst->filter, params->filter_length, params->max_dispersion);
|
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",
|
DEBUG_LOG(LOGF_Refclock, "refclock %s refid=%s poll=%d dpoll=%d filter=%d",
|
||||||
params->driver_name, UTI_RefidToString(inst->ref_id),
|
params->driver_name, UTI_RefidToString(inst->ref_id),
|
||||||
|
|
|
@ -38,6 +38,8 @@ typedef struct {
|
||||||
int poll;
|
int poll;
|
||||||
int filter_length;
|
int filter_length;
|
||||||
int pps_rate;
|
int pps_rate;
|
||||||
|
int min_samples;
|
||||||
|
int max_samples;
|
||||||
uint32_t ref_id;
|
uint32_t ref_id;
|
||||||
uint32_t lock_ref_id;
|
uint32_t lock_ref_id;
|
||||||
double offset;
|
double offset;
|
||||||
|
|
|
@ -207,14 +207,19 @@ void SRC_Finalise(void)
|
||||||
/* Function to create a new instance. This would be called by one of
|
/* Function to create a new instance. This would be called by one of
|
||||||
the individual source-type instance creation routines. */
|
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;
|
SRC_Instance result;
|
||||||
|
|
||||||
assert(initialised);
|
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 = 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) {
|
if (n_sources == max_n_sources) {
|
||||||
/* Reallocate memory */
|
/* Reallocate memory */
|
||||||
|
|
|
@ -65,7 +65,7 @@ typedef enum {
|
||||||
/* Function to create a new instance. This would be called by one of
|
/* Function to create a new instance. This would be called by one of
|
||||||
the individual source-type instance creation routines. */
|
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.
|
/* Function to get rid of a source when it is being unconfigured.
|
||||||
This may cause the current reference source to be reselected, if this
|
This may cause the current reference source to be reselected, if this
|
||||||
|
|
|
@ -43,10 +43,6 @@
|
||||||
to store per source */
|
to store per source */
|
||||||
#define MAX_SAMPLES 64
|
#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,
|
/* This is the assumed worst case bound on an unknown frequency,
|
||||||
2000ppm, which would be pretty bad */
|
2000ppm, which would be pretty bad */
|
||||||
#define WORST_CASE_FREQ_BOUND (2000.0/1.0e6)
|
#define WORST_CASE_FREQ_BOUND (2000.0/1.0e6)
|
||||||
|
@ -68,6 +64,10 @@ struct SST_Stats_Record {
|
||||||
uint32_t refid;
|
uint32_t refid;
|
||||||
IPAddr *ip_addr;
|
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
|
/* Number of samples currently stored. The samples are stored in circular
|
||||||
buffer. */
|
buffer. */
|
||||||
int n_samples;
|
int n_samples;
|
||||||
|
@ -163,8 +163,6 @@ SST_Initialise(void)
|
||||||
logfileid = CNF_GetLogStatistics() ? LOG_FileOpen("statistics",
|
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")
|
" Date (UTC) Time IP Address Std dev'n Est offset Offset sd Diff freq Est skew Stress Ns Bs Nr")
|
||||||
: -1;
|
: -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 */
|
/* This function creates a new instance of the statistics handler */
|
||||||
|
|
||||||
SST_Stats
|
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;
|
SST_Stats inst;
|
||||||
inst = MallocNew(struct SST_Stats_Record);
|
inst = MallocNew(struct SST_Stats_Record);
|
||||||
|
|
||||||
|
inst->min_samples = min_samples;
|
||||||
|
inst->max_samples = max_samples;
|
||||||
|
|
||||||
SST_SetRefid(inst, refid, addr);
|
SST_SetRefid(inst, refid, addr);
|
||||||
SST_ResetInstance(inst);
|
SST_ResetInstance(inst);
|
||||||
|
|
||||||
|
@ -262,7 +263,7 @@ SST_AccumulateSample(SST_Stats inst, struct timeval *sample_time,
|
||||||
|
|
||||||
/* Make room for the new sample */
|
/* Make room for the new sample */
|
||||||
if (inst->n_samples > 0 &&
|
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);
|
prune_register(inst, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,7 +448,7 @@ SST_DoNewRegression(SST_Stats inst)
|
||||||
inst->regression_ok = RGR_FindBestRegression(times_back + inst->runs_samples,
|
inst->regression_ok = RGR_FindBestRegression(times_back + inst->runs_samples,
|
||||||
offsets + inst->runs_samples, weights,
|
offsets + inst->runs_samples, weights,
|
||||||
inst->n_samples, inst->runs_samples,
|
inst->n_samples, inst->runs_samples,
|
||||||
min_samples,
|
inst->min_samples,
|
||||||
&est_intercept, &est_slope, &est_var,
|
&est_intercept, &est_slope, &est_var,
|
||||||
&est_intercept_sd, &est_slope_sd,
|
&est_intercept_sd, &est_slope_sd,
|
||||||
&best_start, &nruns, °rees_of_freedom);
|
&best_start, &nruns, °rees_of_freedom);
|
||||||
|
|
|
@ -38,7 +38,7 @@ extern void SST_Initialise(void);
|
||||||
extern void SST_Finalise(void);
|
extern void SST_Finalise(void);
|
||||||
|
|
||||||
/* This function creates a new instance of the statistics handler */
|
/* 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. */
|
/* This function deletes an instance of the statistics handler. */
|
||||||
extern void SST_DeleteInstance(SST_Stats inst);
|
extern void SST_DeleteInstance(SST_Stats inst);
|
||||||
|
|
|
@ -40,6 +40,8 @@ typedef struct {
|
||||||
int poll_target;
|
int poll_target;
|
||||||
int version;
|
int version;
|
||||||
int max_sources;
|
int max_sources;
|
||||||
|
int min_samples;
|
||||||
|
int max_samples;
|
||||||
uint32_t authkey;
|
uint32_t authkey;
|
||||||
double max_delay;
|
double max_delay;
|
||||||
double max_delay_ratio;
|
double max_delay_ratio;
|
||||||
|
@ -57,6 +59,8 @@ typedef struct {
|
||||||
#define SRC_DEFAULT_MINSTRATUM 0
|
#define SRC_DEFAULT_MINSTRATUM 0
|
||||||
#define SRC_DEFAULT_POLLTARGET 6
|
#define SRC_DEFAULT_POLLTARGET 6
|
||||||
#define SRC_DEFAULT_MAXSOURCES 4
|
#define SRC_DEFAULT_MAXSOURCES 4
|
||||||
|
#define SRC_DEFAULT_MINSAMPLES (-1)
|
||||||
|
#define SRC_DEFAULT_MAXSAMPLES (-1)
|
||||||
#define INACTIVE_AUTHKEY 0
|
#define INACTIVE_AUTHKEY 0
|
||||||
|
|
||||||
#endif /* GOT_SRCPARAMS_H */
|
#endif /* GOT_SRCPARAMS_H */
|
||||||
|
|
Loading…
Reference in a new issue