diff --git a/ntp_core.c b/ntp_core.c index d87510e..40f77b4 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -636,18 +636,6 @@ transmit_timeout(void *arg) 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, @@ -655,7 +643,14 @@ transmit_timeout(void *arg) 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; @@ -700,7 +695,7 @@ transmit_timeout(void *arg) 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: @@ -1074,16 +1069,17 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins 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); } } @@ -1202,7 +1198,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins 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. */ @@ -1714,7 +1710,7 @@ NCR_TakeSourceOffline(NCR_Instance inst) inst->timer_running = 0; inst->opmode = MD_OFFLINE; /* Mark source unreachable */ - SRC_UnsetReachable(inst->source); + SRC_ResetReachability(inst->source); } break; case MD_OFFLINE: diff --git a/refclock.c b/refclock.c index 4cfc343..1922ebb 100644 --- a/refclock.c +++ b/refclock.c @@ -69,7 +69,6 @@ struct RCL_Instance_Record { int driver_poll; int driver_polled; int poll; - int missed_samples; int leap_status; int pps_rate; struct MedianFilter filter; @@ -175,7 +174,6 @@ RCL_AddRefclock(RefclockParameters *params) 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; @@ -255,6 +253,7 @@ RCL_StartRefclocks(void) 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) { @@ -519,16 +518,13 @@ poll_timeout(void *arg) 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); } } diff --git a/sources.c b/sources.c index 10e4295..0c0eb2c 100644 --- a/sources.c +++ b/sources.c @@ -90,9 +90,11 @@ struct SRC_Instance_Record { 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; @@ -127,6 +129,9 @@ static int selected_source_index; /* Which source index is currently selected (set to INVALID_SOURCE if no current valid reference) */ +/* Keep reachability status for last 8 samples */ +#define REACH_BITS 8 + /* ================================================== */ /* 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->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; @@ -218,10 +224,7 @@ void SRC_DestroyInstance(SRC_Instance instance) 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; @@ -304,9 +307,9 @@ void SRC_AccumulateSample /* ================================================== */ 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)); @@ -319,9 +322,9 @@ SRC_SetReachable(SRC_Instance 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), @@ -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 compare_sort_elements(const void *a, const void *b) { @@ -416,7 +443,8 @@ SRC_SelectSource(unsigned long match_addr) n_sel_sources = 0; for (i=0; ireachable && 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, diff --git a/sources.h b/sources.h index 4351e13..ae7e3c7 100644 --- a/sources.h +++ b/sources.h @@ -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 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