@@ -440,7 +440,7 @@ void NtpServer::processPacket(const std::vector<uint8_t> &data,
440440 }
441441
442442 NtpPacket response_packet = NtpPacket::createServerResponse (
443- request_packet, config_->stratum , config_-> reference_id );
443+ request_packet, config_->stratum , effectiveReferenceId () );
444444 applyDynamicStratum ();
445445 const std::string selected_upstream = selectUpstreamServer ();
446446 if (!selected_upstream.empty ()) {
@@ -456,6 +456,13 @@ void NtpServer::processPacket(const std::vector<uint8_t> &data,
456456 " :" + std::to_string (client_port) + " : " +
457457 std::string (std::strerror (errno)));
458458 stats_.total_errors ++;
459+ if (config_ && config_->enable_upstream_failover && !selected_upstream.empty ()) {
460+ auto it = std::find (healthy_upstreams_.begin (), healthy_upstreams_.end (),
461+ selected_upstream);
462+ if (it != healthy_upstreams_.end ()) {
463+ healthy_upstreams_.erase (it);
464+ }
465+ }
459466 return ;
460467 }
461468
@@ -792,20 +799,23 @@ std::string NtpServer::selectUpstreamServer() {
792799 if (!config_ || config_->upstream_servers .empty ()) {
793800 return std::string ();
794801 }
795- if (config_->upstream_servers .size () == 1 ) {
796- return config_->upstream_servers .front ();
802+ if (healthy_upstreams_.empty ()) {
803+ healthy_upstreams_ = config_->upstream_servers ;
804+ }
805+ if (healthy_upstreams_.size () == 1 ) {
806+ return healthy_upstreams_.front ();
797807 }
798808 switch (config_->upstream_selection_algorithm ) {
799809 case NtpConfig::UpstreamSelectionAlgorithm::RANDOM : {
800- std::uniform_int_distribution<size_t > dist (0 , config_-> upstream_servers .size () - 1 );
801- return config_-> upstream_servers [dist (rng_)];
810+ std::uniform_int_distribution<size_t > dist (0 , healthy_upstreams_ .size () - 1 );
811+ return healthy_upstreams_ [dist (rng_)];
802812 }
803813 case NtpConfig::UpstreamSelectionAlgorithm::LEAST_ERRORS :
804814 // For now fallback to round-robin until per-upstream error accounting is added.
805815 case NtpConfig::UpstreamSelectionAlgorithm::ROUND_ROBIN :
806816 default : {
807- const size_t idx = upstream_rr_index_.fetch_add (1 ) % config_-> upstream_servers .size ();
808- return config_-> upstream_servers [idx];
817+ const size_t idx = upstream_rr_index_.fetch_add (1 ) % healthy_upstreams_ .size ();
818+ return healthy_upstreams_ [idx];
809819 }
810820 }
811821}
@@ -824,4 +834,22 @@ void NtpServer::applyDynamicStratum() {
824834 }
825835}
826836
837+ std::string NtpServer::effectiveReferenceId () const {
838+ if (!config_ || !config_->enable_reference_clock_support ) {
839+ return config_ ? config_->reference_id : " LOCL" ;
840+ }
841+ std::string source = config_->reference_clock_source ;
842+ std::transform (source.begin (), source.end (), source.begin (), ::tolower);
843+ if (source == " gps" ) {
844+ return " GPS " ;
845+ }
846+ if (source == " atomic" ) {
847+ return " ATOM" ;
848+ }
849+ if (source == " hardware" ) {
850+ return " HARD" ;
851+ }
852+ return config_->reference_id .empty () ? " LOCL" : config_->reference_id ;
853+ }
854+
827855} // namespace simple_ntpd
0 commit comments