inst->presend_done = 0; /* Reset for next time */
++inst->tx_count;
- if (inst->tx_count >= 9) {
- /* Mark source unreachable */
- SRC_UnsetReachable(inst->source);
- } else if (inst->tx_count >= 3) {
- if (inst->auto_offline) {
- NCR_TakeSourceOffline(inst);
- }
- /* Do reselection */
- SRC_SelectSource(0);
- } else {
- /* Nothing */
- }
/* If the source loses connectivity, back off the sampling rate to reduce
wasted sampling. If it's the source to which we are currently locked,
if (inst->tx_count >= 2) {
/* Implies we have missed at least one transmission */
+
adjust_poll(inst, SRC_IsSyncPeer(inst->source) ? 0.1 : 0.25);
+
+ SRC_UpdateReachability(inst->source, 0);
+
+ if (inst->auto_offline && inst->tx_count >= 3) {
+ NCR_TakeSourceOffline(inst);
+ }
}
my_mode = inst->mode;
case MD_OFFLINE:
do_timer = 0;
/* Mark source unreachable */
- SRC_UnsetReachable(inst->source);
+ SRC_ResetReachability(inst->source);
break;
case MD_BURST_WAS_ONLINE:
case MD_BURST_WAS_OFFLINE:
if (valid_header && valid_data) {
inst->tx_count = 0;
+ SRC_UpdateReachability(inst->source, 1);
/* Mark the source as suitable for synchronisation when both header and
data are good, unmark when header is not good (i.e. the stratum is
higher than ours) */
if (good_header) {
if (good_data) {
- SRC_SetReachable(inst->source);
+ SRC_SetSelectable(inst->source);
}
} else {
- SRC_UnsetReachable(inst->source);
+ SRC_UnsetSelectable(inst->source);
}
}
case MD_OFFLINE:
requeue_transmit = 0;
/* Mark source unreachable */
- SRC_UnsetReachable(inst->source);
+ SRC_ResetReachability(inst->source);
break; /* Even if we've received something, we don't want to
transmit back. This might be a symmetric active peer
that is trying to talk to us. */
inst->timer_running = 0;
inst->opmode = MD_OFFLINE;
/* Mark source unreachable */
- SRC_UnsetReachable(inst->source);
+ SRC_ResetReachability(inst->source);
}
break;
case MD_OFFLINE:
int driver_poll;
int driver_polled;
int poll;
- int missed_samples;
int leap_status;
int pps_rate;
struct MedianFilter filter;
inst->driver_parameter_length = 0;
inst->driver_poll = params->driver_poll;
inst->poll = params->poll;
- inst->missed_samples = 0;
inst->driver_polled = 0;
inst->leap_status = 0;
inst->pps_rate = params->pps_rate;
for (i = 0; i < n_sources; i++) {
RCL_Instance inst = &refclocks[i];
+ SRC_SetSelectable(inst->source);
inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
if (inst->lock_ref) {
else
stratum = 0;
- SRC_SetReachable(inst->source);
+ SRC_UpdateReachability(inst->source, 1);
SRC_AccumulateSample(inst->source, &sample_time, offset,
inst->delay, dispersion, inst->delay, dispersion, stratum, inst->leap_status);
log_sample(inst, &sample_time, 1, 0, 0.0, offset, dispersion);
- inst->missed_samples = 0;
} else {
- inst->missed_samples++;
- if (inst->missed_samples > 9)
- SRC_UnsetReachable(inst->source);
+ SRC_UpdateReachability(inst->source, 0);
}
}
reference _it_ is sync'd to) */
IPAddr *ip_addr; /* Its IP address if NTP source */
- /* Flag indicating that we are receiving packets with valid headers
- from this source and can use it as a reference */
- int reachable;
+ /* Flag indicating that we can use this source as a reference */
+ int selectable;
+
+ /* Reachability register */
+ int reachability;
/* Flag indicating the status of the source */
SRC_Status status;
selected (set to INVALID_SOURCE
if no current valid reference) */
+/* Keep reachability status for last 8 samples */
+#define REACH_BITS 8
+
/* ================================================== */
/* Forward prototype */
result->leap_status = LEAP_Normal;
result->ref_id = ref_id;
result->ip_addr = addr;
- result->reachable = 0;
+ result->selectable = 0;
+ result->reachability = 0;
result->status = SRC_BAD_STATS;
result->type = type;
result->sel_option = sel_option;
assert(initialised);
- if (instance->index == selected_source_index) {
- instance->reachable = 0;
- SRC_SelectSource(0);
- }
+ SRC_UnsetSelectable(instance);
SST_DeleteInstance(instance->stats);
dead_index = instance->index;
/* ================================================== */
void
-SRC_SetReachable(SRC_Instance inst)
+SRC_SetSelectable(SRC_Instance inst)
{
- inst->reachable = 1;
+ inst->selectable = 1;
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "%s", source_to_string(inst));
/* ================================================== */
void
-SRC_UnsetReachable(SRC_Instance inst)
+SRC_UnsetSelectable(SRC_Instance inst)
{
- inst->reachable = 0;
+ inst->selectable = 0;
#ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "%s%s", source_to_string(inst),
/* ================================================== */
+void
+SRC_UpdateReachability(SRC_Instance inst, int reachable)
+{
+ inst->reachability <<= 1;
+ inst->reachability |= !!reachable;
+ inst->reachability &= ~(-1 << REACH_BITS);
+
+ if (!reachable && inst->index == selected_source_index) {
+ /* Try to select a better source */
+ SRC_SelectSource(0);
+ }
+}
+
+/* ================================================== */
+
+void
+SRC_ResetReachability(SRC_Instance inst)
+{
+ inst->reachability = 0;
+ SRC_UpdateReachability(inst, 0);
+}
+
+/* ================================================== */
+
static int
compare_sort_elements(const void *a, const void *b)
{
n_sel_sources = 0;
for (i=0; i<n_sources; i++) {
- if (sources[i]->reachable && sources[i]->sel_option != SRC_SelectNoselect) {
+ if (sources[i]->selectable && sources[i]->reachability &&
+ sources[i]->sel_option != SRC_SelectNoselect) {
si = &(sources[i]->sel_info);
SST_GetSelectionData(sources[i]->stats, &now,
/* This routine indicates that packets with valid headers are being
received from the designated source */
-extern void SRC_SetReachable(SRC_Instance instance);
+extern void SRC_SetSelectable(SRC_Instance instance);
/* This routine indicates that we are no longer receiving packets with
valid headers from the designated source */
-extern void SRC_UnsetReachable(SRC_Instance instance);
+extern void SRC_UnsetSelectable(SRC_Instance instance);
+
+/* This routine updates the reachability register */
+extern void SRC_UpdateReachability(SRC_Instance inst, int reachable);
+
+/* This routine marks the source unreachable */
+extern void SRC_ResetReachability(SRC_Instance inst);
/* This routine is used to select the best source from amongst those
we currently have valid data on, and use it as the tracking base