Track reachability in sources module

Add new flag to source struct to indicate when source is selectable
(packets with good headers are received) and use a reachability
register for last 8 samples instead of the reachable flag. Source
drivers now provide only reachability updates.
This commit is contained in:
Miroslav Lichvar 2010-12-16 16:01:29 +01:00
parent ff69e86559
commit 0c4968ec51
4 changed files with 65 additions and 39 deletions

View file

@ -636,18 +636,6 @@ transmit_timeout(void *arg)
inst->presend_done = 0; /* Reset for next time */ inst->presend_done = 0; /* Reset for next time */
++inst->tx_count; ++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 /* 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, wasted sampling. If it's the source to which we are currently locked,
@ -655,7 +643,14 @@ transmit_timeout(void *arg)
if (inst->tx_count >= 2) { if (inst->tx_count >= 2) {
/* Implies we have missed at least one transmission */ /* Implies we have missed at least one transmission */
adjust_poll(inst, SRC_IsSyncPeer(inst->source) ? 0.1 : 0.25); 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; my_mode = inst->mode;
@ -700,7 +695,7 @@ transmit_timeout(void *arg)
case MD_OFFLINE: case MD_OFFLINE:
do_timer = 0; do_timer = 0;
/* Mark source unreachable */ /* Mark source unreachable */
SRC_UnsetReachable(inst->source); SRC_ResetReachability(inst->source);
break; break;
case MD_BURST_WAS_ONLINE: case MD_BURST_WAS_ONLINE:
case MD_BURST_WAS_OFFLINE: case MD_BURST_WAS_OFFLINE:
@ -1074,16 +1069,17 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
if (valid_header && valid_data) { if (valid_header && valid_data) {
inst->tx_count = 0; inst->tx_count = 0;
SRC_UpdateReachability(inst->source, 1);
/* Mark the source as suitable for synchronisation when both header and /* 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 data are good, unmark when header is not good (i.e. the stratum is
higher than ours) */ higher than ours) */
if (good_header) { if (good_header) {
if (good_data) { if (good_data) {
SRC_SetReachable(inst->source); SRC_SetSelectable(inst->source);
} }
} else { } else {
SRC_UnsetReachable(inst->source); SRC_UnsetSelectable(inst->source);
} }
} }
@ -1202,7 +1198,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
case MD_OFFLINE: case MD_OFFLINE:
requeue_transmit = 0; requeue_transmit = 0;
/* Mark source unreachable */ /* Mark source unreachable */
SRC_UnsetReachable(inst->source); SRC_ResetReachability(inst->source);
break; /* Even if we've received something, we don't want to break; /* Even if we've received something, we don't want to
transmit back. This might be a symmetric active peer transmit back. This might be a symmetric active peer
that is trying to talk to us. */ that is trying to talk to us. */
@ -1714,7 +1710,7 @@ NCR_TakeSourceOffline(NCR_Instance inst)
inst->timer_running = 0; inst->timer_running = 0;
inst->opmode = MD_OFFLINE; inst->opmode = MD_OFFLINE;
/* Mark source unreachable */ /* Mark source unreachable */
SRC_UnsetReachable(inst->source); SRC_ResetReachability(inst->source);
} }
break; break;
case MD_OFFLINE: case MD_OFFLINE:

View file

@ -69,7 +69,6 @@ struct RCL_Instance_Record {
int driver_poll; int driver_poll;
int driver_polled; int driver_polled;
int poll; int poll;
int missed_samples;
int leap_status; int leap_status;
int pps_rate; int pps_rate;
struct MedianFilter filter; struct MedianFilter filter;
@ -175,7 +174,6 @@ RCL_AddRefclock(RefclockParameters *params)
inst->driver_parameter_length = 0; inst->driver_parameter_length = 0;
inst->driver_poll = params->driver_poll; inst->driver_poll = params->driver_poll;
inst->poll = params->poll; inst->poll = params->poll;
inst->missed_samples = 0;
inst->driver_polled = 0; inst->driver_polled = 0;
inst->leap_status = 0; inst->leap_status = 0;
inst->pps_rate = params->pps_rate; inst->pps_rate = params->pps_rate;
@ -255,6 +253,7 @@ RCL_StartRefclocks(void)
for (i = 0; i < n_sources; i++) { for (i = 0; i < n_sources; i++) {
RCL_Instance inst = &refclocks[i]; RCL_Instance inst = &refclocks[i];
SRC_SetSelectable(inst->source);
inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst); inst->timeout_id = SCH_AddTimeoutByDelay(0.0, poll_timeout, (void *)inst);
if (inst->lock_ref) { if (inst->lock_ref) {
@ -519,16 +518,13 @@ poll_timeout(void *arg)
else else
stratum = 0; stratum = 0;
SRC_SetReachable(inst->source); SRC_UpdateReachability(inst->source, 1);
SRC_AccumulateSample(inst->source, &sample_time, offset, SRC_AccumulateSample(inst->source, &sample_time, offset,
inst->delay, dispersion, inst->delay, dispersion, stratum, inst->leap_status); inst->delay, dispersion, inst->delay, dispersion, stratum, inst->leap_status);
log_sample(inst, &sample_time, 1, 0, 0.0, offset, dispersion); log_sample(inst, &sample_time, 1, 0, 0.0, offset, dispersion);
inst->missed_samples = 0;
} else { } else {
inst->missed_samples++; SRC_UpdateReachability(inst->source, 0);
if (inst->missed_samples > 9)
SRC_UnsetReachable(inst->source);
} }
} }

View file

@ -90,9 +90,11 @@ struct SRC_Instance_Record {
reference _it_ is sync'd to) */ reference _it_ is sync'd to) */
IPAddr *ip_addr; /* Its IP address if NTP source */ IPAddr *ip_addr; /* Its IP address if NTP source */
/* Flag indicating that we are receiving packets with valid headers /* Flag indicating that we can use this source as a reference */
from this source and can use it as a reference */ int selectable;
int reachable;
/* Reachability register */
int reachability;
/* Flag indicating the status of the source */ /* Flag indicating the status of the source */
SRC_Status status; SRC_Status status;
@ -127,6 +129,9 @@ static int selected_source_index; /* Which source index is currently
selected (set to INVALID_SOURCE selected (set to INVALID_SOURCE
if no current valid reference) */ if no current valid reference) */
/* Keep reachability status for last 8 samples */
#define REACH_BITS 8
/* ================================================== */ /* ================================================== */
/* Forward prototype */ /* Forward prototype */
@ -196,7 +201,8 @@ SRC_Instance SRC_CreateNewInstance(unsigned long ref_id, SRC_Type type, SRC_Sele
result->leap_status = LEAP_Normal; result->leap_status = LEAP_Normal;
result->ref_id = ref_id; result->ref_id = ref_id;
result->ip_addr = addr; result->ip_addr = addr;
result->reachable = 0; result->selectable = 0;
result->reachability = 0;
result->status = SRC_BAD_STATS; result->status = SRC_BAD_STATS;
result->type = type; result->type = type;
result->sel_option = sel_option; result->sel_option = sel_option;
@ -218,10 +224,7 @@ void SRC_DestroyInstance(SRC_Instance instance)
assert(initialised); assert(initialised);
if (instance->index == selected_source_index) { SRC_UnsetSelectable(instance);
instance->reachable = 0;
SRC_SelectSource(0);
}
SST_DeleteInstance(instance->stats); SST_DeleteInstance(instance->stats);
dead_index = instance->index; dead_index = instance->index;
@ -304,9 +307,9 @@ void SRC_AccumulateSample
/* ================================================== */ /* ================================================== */
void void
SRC_SetReachable(SRC_Instance inst) SRC_SetSelectable(SRC_Instance inst)
{ {
inst->reachable = 1; inst->selectable = 1;
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "%s", source_to_string(inst)); LOG(LOGS_INFO, LOGF_Sources, "%s", source_to_string(inst));
@ -319,9 +322,9 @@ SRC_SetReachable(SRC_Instance inst)
/* ================================================== */ /* ================================================== */
void void
SRC_UnsetReachable(SRC_Instance inst) SRC_UnsetSelectable(SRC_Instance inst)
{ {
inst->reachable = 0; inst->selectable = 0;
#ifdef TRACEON #ifdef TRACEON
LOG(LOGS_INFO, LOGF_Sources, "%s%s", source_to_string(inst), LOG(LOGS_INFO, LOGF_Sources, "%s%s", source_to_string(inst),
@ -338,6 +341,30 @@ SRC_UnsetReachable(SRC_Instance 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 static int
compare_sort_elements(const void *a, const void *b) compare_sort_elements(const void *a, const void *b)
{ {
@ -416,7 +443,8 @@ SRC_SelectSource(unsigned long match_addr)
n_sel_sources = 0; n_sel_sources = 0;
for (i=0; i<n_sources; i++) { 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); si = &(sources[i]->sel_info);
SST_GetSelectionData(sources[i]->stats, &now, SST_GetSelectionData(sources[i]->stats, &now,

View file

@ -120,11 +120,17 @@ extern void SRC_AccumulateSample(SRC_Instance instance, struct timeval *sample_t
/* This routine indicates that packets with valid headers are being /* This routine indicates that packets with valid headers are being
received from the designated source */ 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 /* This routine indicates that we are no longer receiving packets with
valid headers from the designated source */ 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 /* 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 we currently have valid data on, and use it as the tracking base