@item precision
Refclock precision (in seconds). The default is 1e-6 (1 microsecond)
for SHM refclock, and 1e-9 (1 nanosecond) for SOCK and PPS refclocks.
+@item prefer
+Prefer this source over sources without prefer option.
+@item noselect
+Never select this source. This is particularly useful for monitoring.
@end table
@c }}}
to be unrealiable or inaccurate and which should be used only when other
sources are unreachable.
+@item prefer
+Prefer this source over sources without prefer option.
+
+@item noselect
+Never select this source. This is particularly useful for monitoring.
+
@end table
@c }}}
@c {{{ tempcomp
if (data.params.min_stratum) {
fprintf(stderr, "Option minstratum not supported\n");
break;
+ } else if (data.params.sel_option != SRC_SelectNormal) {
+ fprintf(stderr, "Options noselect and prefer not supported\n");
+ break;
}
msg->data.ntp_source.port = htonl((unsigned long) data.port);
params.iburst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_IBURST ? 1 : 0;
params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
- params.min_stratum = 0; /* not transmitted in cmdmon protocol yet */
+
+ /* not transmitted in cmdmon protocol yet */
+ params.min_stratum = 0;
+ params.sel_option = SRC_SelectNormal;
+
status = NSR_AddSource(&rem_addr, NTP_SERVER, ¶ms);
switch (status) {
case NSR_Success:
params.iburst = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_IBURST ? 1 : 0;
params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
- params.min_stratum = 0; /* not transmitted in cmdmon protocol yet */
+
+ /* not transmitted in cmdmon protocol yet */
+ params.min_stratum = 0;
+ params.sel_option = SRC_SelectNormal;
+
status = NSR_AddSource(&rem_addr, NTP_PEER, ¶ms);
switch (status) {
case NSR_Success:
src->params.auto_offline = 0;
src->params.iburst = 0;
src->params.min_stratum = 0;
+ src->params.sel_option = SRC_SelectNormal;
result = CPS_Success;
} else {
line += n;
}
+
+ } else if (!strncasecmp(cmd, "noselect", 8)) {
+ src->params.sel_option = SRC_SelectNoselect;
+
+ } else if (!strncasecmp(cmd, "prefer", 6)) {
+ src->params.sel_option = SRC_SelectPrefer;
} else {
result = CPS_BadOption;
const char *tmp;
char name[5], cmd[10 + 1], *param;
unsigned char ref[5];
+ SRC_SelectOption sel_option;
i = n_refclock_sources;
if (i >= MAX_RCL_SOURCES)
precision = 0.0;
ref_id = 0;
lock_ref_id = 0;
+ sel_option = SRC_SelectNormal;
if (sscanf(line, "%4s%n", name, &n) != 1) {
LOG(LOGS_WARN, LOGF_Configure, "Could not read refclock driver name at line %d", line_number);
} else if (!strncasecmp(cmd, "precision", 9)) {
if (sscanf(line, "%lf%n", &precision, &n) != 1)
break;
+ } else if (!strncasecmp(cmd, "noselect", 8)) {
+ n = 0;
+ sel_option = SRC_SelectNoselect;
+ } else if (!strncasecmp(cmd, "prefer", 6)) {
+ n = 0;
+ sel_option = SRC_SelectPrefer;
} else {
LOG(LOGS_WARN, LOGF_Configure, "Unknown refclock parameter %s at line %d", cmd, line_number);
break;
refclock_sources[i].offset = offset;
refclock_sources[i].delay = delay;
refclock_sources[i].precision = precision;
+ refclock_sources[i].sel_option = sel_option;
refclock_sources[i].ref_id = ref_id;
refclock_sources[i].lock_ref_id = lock_ref_id;
result->local_poll = params->minpoll;
/* Create a source instance for this NTP source */
- result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr), SRC_NTP, &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);
result->local_rx.tv_sec = 0;
result->local_rx.tv_usec = 0;
filter_init(&inst->filter, params->filter_length);
- inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, NULL);
+ inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_option, NULL);
#if 0
LOG(LOGS_INFO, LOGF_Refclock, "refclock added poll=%d dpoll=%d filter=%d",
double offset;
double delay;
double precision;
+ SRC_SelectOption sel_option;
} RefclockParameters;
typedef struct RCL_Instance_Record *RCL_Instance;
/* Type of the source */
SRC_Type type;
+ /* Options used when selecting sources */
+ SRC_SelectOption sel_option;
+
struct SelectInfo sel_info;
};
/* Function to create a new instance. This would be called by one of
the individual source-type instance creation routines. */
-SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, IPAddr *addr)
+SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, SRC_SelectOption sel_option, IPAddr *addr)
{
SRC_Instance result;
result->reachable = 0;
result->status = SRC_BAD_STATS;
result->type = type;
+ result->sel_option = sel_option;
n_sources++;
n_reachable_sources = 0;
for (i=0; i<n_sources; i++) {
- if (sources[i]->reachable) {
+ if (sources[i]->reachable && sources[i]->sel_option != SRC_SelectNoselect) {
++n_reachable_sources;
}
n_sel_sources = j;
- /* Now find minimum stratum. If none are left now,
- tough. RFC1305 is not so harsh on pruning sources due to
- excess variance, which prevents this from happening */
-
if (n_sel_sources > 0) {
+ /* Accept leap second status if more than half of selectable sources agree */
+
+ for (i=j1=j2=0; i<n_sel_sources; i++) {
+ index = sel_sources[i];
+ if (sources[index]->leap_status == LEAP_InsertSecond) {
+ j1++;
+ } else if (sources[index]->leap_status == LEAP_DeleteSecond) {
+ j2++;
+ }
+ }
+
+ if (j1 > n_sel_sources / 2) {
+ leap_status = LEAP_InsertSecond;
+ } else if (j2 > n_sel_sources / 2) {
+ leap_status = LEAP_DeleteSecond;
+ }
+
+ /* If there are any sources with prefer option, reduce the list again
+ only to the prefer sources */
+ for (i=j=0; i<n_sel_sources; i++) {
+ if (sources[sel_sources[i]]->sel_option == SRC_SelectPrefer) {
+ sel_sources[j++] = sel_sources[i];
+ }
+ }
+ if (j > 0) {
+ n_sel_sources = j;
+ }
+
+ /* Now find minimum stratum. If none are left now,
+ tough. RFC1305 is not so harsh on pruning sources due to
+ excess variance, which prevents this from happening */
+
index = sel_sources[0];
min_stratum = sources[index]->sel_info.stratum;
for (i=1; i<n_sel_sources; i++) {
total_root_dispersion = (src_accrued_dispersion +
sources[selected_source_index]->sel_info.root_dispersion);
- /* Accept leap second status if more than half of selectable sources agree */
-
- for (i=j1=j2=0; i<n_sel_sources; i++) {
- index = sel_sources[i];
- if (sources[index]->leap_status == LEAP_InsertSecond) {
- j1++;
- } else if (sources[index]->leap_status == LEAP_DeleteSecond) {
- j2++;
- }
- }
-
- if (j1 > n_sel_sources / 2) {
- leap_status = LEAP_InsertSecond;
- } else if (j2 > n_sel_sources / 2) {
- leap_status = LEAP_DeleteSecond;
- }
-
if ((match_addr == 0) ||
(match_addr == sources[selected_source_index]->ref_id)) {
SRC_REFCLOCK /* Rerefence clock */
} SRC_Type;
+/* Options used when selecting sources */
+typedef enum {
+ SRC_SelectNormal,
+ SRC_SelectNoselect,
+ SRC_SelectPrefer
+} SRC_SelectOption;
+
/* 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(unsigned long ref_id, SRC_Type type, IPAddr *addr);
+extern SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, SRC_SelectOption sel_option, IPAddr *addr);
/* Function to get rid of a source when it is being unconfigured.
This may cause the current reference source to be reselected, if this
#ifndef GOT_SRCPARAMS_H
#define GOT_SRCPARAMS_H
+#include "sources.h"
+
typedef struct {
int minpoll;
int maxpoll;
unsigned long authkey;
double max_delay;
double max_delay_ratio;
+ SRC_SelectOption sel_option;
} SourceParameters;
#define INACTIVE_AUTHKEY 0UL