From f7f6ad2a60c9aacd1d36bc2e6b377d163f2e12d8 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sun, 19 Jun 2022 13:19:30 +0100 Subject: [PATCH] Remove code for qualifying an Anounce message -- it is not used in 802.1AS. Simplify code by removing redunadant and obselete code, variables and fields. --- nqptp-clock-sources.c | 88 +------- nqptp-clock-sources.h | 15 +- nqptp-message-handlers.c | 443 ++++++++++++++------------------------- 3 files changed, 160 insertions(+), 386 deletions(-) diff --git a/nqptp-clock-sources.c b/nqptp-clock-sources.c index b7698d5..3ef1542 100644 --- a/nqptp-clock-sources.c +++ b/nqptp-clock-sources.c @@ -65,7 +65,7 @@ int get_client_id(char *client_shared_memory_interface_name) { else i++; } - + if (response == -1) { // no match, so create one i = 0; while ((response == -1) && (i < MAX_CLIENTS)) { @@ -274,8 +274,6 @@ void manage_clock_sources(uint64_t reception_time, clock_source_private_data *cl memset(&clocks_private_info[i], 0, sizeof(clock_source_private_data)); if (old_flags != 0) { update_master(0); // TODO -- won't be needed - } else { - debug_log_nqptp_status(2); } } } @@ -333,53 +331,6 @@ void update_clock_self_identifications(clock_source_private_data *clocks_private } } -void debug_log_nqptp_status(__attribute__((unused)) int level) { - /* - int records_in_use = 0; - int i; - for (i = 0; i < MAX_CLOCKS; i++) - if ((clocks_private[i].flags & (1 << clock_is_in_use)) != 0) - records_in_use++; - debug(level, ""); - if (records_in_use > 0) { - debug(level, "Current NQPTP Status:"); - uint32_t peer_mask = (1 << clock_is_a_timing_peer); - uint32_t peer_clock_mask = peer_mask | (1 << clock_is_valid); - uint32_t peer_master_mask = peer_clock_mask | (1 << clock_is_master); - uint32_t peer_becoming_master_mask = peer_clock_mask | (1 << clock_is_becoming_master); - uint32_t non_peer_clock_mask = (1 << clock_is_valid); - uint32_t non_peer_master_mask = non_peer_clock_mask | (1 << clock_is_master); - for (i = 0; i < MAX_CLOCKS; i++) { - if ((clocks_private[i].flags & (1 << clock_is_in_use)) != 0) { - if ((clocks_private[i].flags & peer_master_mask) == peer_master_mask) { - debug(level, " Peer Master: %" PRIx64 " %s.", clocks_private[i].clock_id, - clocks_private[i].ip); - } else if ((clocks_private[i].flags & peer_becoming_master_mask) == - peer_becoming_master_mask) { - debug(level, " Peer Becoming Master: %" PRIx64 " %s.", clocks_private[i].clock_id, - clocks_private[i].ip); - } else if ((clocks_private[i].flags & peer_clock_mask) == peer_clock_mask) { - debug(level, " Peer Clock: %" PRIx64 " %s.", clocks_private[i].clock_id, - clocks_private[i].ip); - } else if ((clocks_private[i].flags & peer_mask) == peer_mask) { - debug(level, " Peer: %s.", clocks_private[i].ip); - } else if ((clocks_private[i].flags & non_peer_master_mask) == non_peer_master_mask) { - debug(level, " Non Peer Master: %" PRIx64 " %s.", clocks_private[i].clock_id, - clocks_private[i].ip); - } else if ((clocks_private[i].flags & non_peer_clock_mask) == non_peer_clock_mask) { - debug(level, " Non Peer Clock: %16" PRIx64 " %s.", clocks_private[i].clock_id, - clocks_private[i].ip); - } else { - debug(level, " Non Peer Record: %s.", clocks_private[i].ip); - } - } - } - } else { - debug(level, "Current NQPTP Status: no records in use."); - } - */ -} - int uint32_cmp(uint32_t a, uint32_t b, const char *cause) { // returns -1 if a is less than b, 0 if a = b, +1 if a is greater than b if (a == b) { @@ -436,14 +387,11 @@ void update_master(int client_id) { if (old_master == -1) old_master = i; // find old master clocks_private[i].client_flags[client_id] &= ~(1 << clock_is_master); // turn them all off - clocks_private[i].client_flags[client_id] &= - ~(1 << clock_is_becoming_master); // turn them all off } int best_so_far = -1; int timing_peer_count = 0; - // uint32_t clock_specific_acceptance_mask = (1 << clock_is_qualified) | (1 << clock_is_valid); - uint32_t clock_specific_acceptance_mask = (1 << clock_is_qualified); + uint32_t clock_specific_acceptance_mask = (1 << clock_is_announced); uint32_t client_specific_acceptance_mask = (1 << clock_is_a_timing_peer); for (i = 0; i < MAX_CLOCKS; i++) { if (((clocks_private[i].flags & clock_specific_acceptance_mask) == @@ -515,37 +463,13 @@ void update_master(int client_id) { update_master_clock_info(client_id, 0, NULL, 0, 0, 0); //} if (timing_peer_count == 0) - debug(2, "no valid qualified clocks "); + debug(2, "empty timing peer group "); else debug(1, "no master clock!"); } else { - // we found a master clock - - if (old_master != best_so_far) { - // if the master is a new one - // now, if it's already a master somewhere, it doesn't need to resync - int clock_is_a_master_somewhere = 0; - int temp_client_id; - for (temp_client_id = 0; temp_client_id < MAX_CLIENTS; temp_client_id++) { - if ((clocks_private[best_so_far].client_flags[temp_client_id] & (1 << clock_is_master)) != - 0) { - clock_is_a_master_somewhere = 1; - } - } - if (clock_is_a_master_somewhere == 0) { - clocks_private[best_so_far].client_flags[client_id] |= (1 << clock_is_master); -// clocks_private[best_so_far].client_flags[client_id] |= (1 << clock_is_becoming_master); -// clocks_private[best_so_far].last_sync_time = 0; // declare it was never synced before - - } else { - clocks_private[best_so_far].client_flags[client_id] |= (1 << clock_is_master); - } - } else { - // if it's the same one as before - clocks_private[best_so_far].client_flags[client_id] |= (1 << clock_is_master); - } + // we mark the master clock we found + clocks_private[best_so_far].client_flags[client_id] |= (1 << clock_is_master); } - debug_log_nqptp_status(2); } void update_master_clock_info(int client_id, uint64_t master_clock_id, const char *ip, @@ -553,8 +477,6 @@ void update_master_clock_info(int client_id, uint64_t master_clock_id, const cha uint64_t mastership_start_time) { if (clients[client_id].shm_interface_name[0] != '\0') { // debug(1,"update_master_clock_info start"); - if (clients[client_id].shared_memory->master_clock_id != master_clock_id) - debug_log_nqptp_status(1); int rc = pthread_mutex_lock(&clients[client_id].shared_memory->shm_mutex); if (rc != 0) warn("Can't acquire mutex to update master clock!"); diff --git a/nqptp-clock-sources.h b/nqptp-clock-sources.h index 760a051..04fd16e 100644 --- a/nqptp-clock-sources.h +++ b/nqptp-clock-sources.h @@ -26,8 +26,7 @@ typedef enum { clock_is_in_use, clock_is_one_of_ours, clock_is_a_timing_peer, - clock_is_qualified, - clock_is_becoming_master, + clock_is_announced, clock_is_master } clock_flags; @@ -38,19 +37,13 @@ typedef struct { int follow_up_number; int announcements_without_followups; // add 1 for every announce, reset with a followup uint64_t clock_id; - uint64_t local_time; // the local time when the offset was calculated - uint64_t source_time; - uint64_t local_to_source_time_offset; // add this to the local time to get source time - uint64_t previous_offset, previous_offset_time, last_sync_time; + uint64_t previous_offset, previous_offset_time; uint64_t mastership_start_time; // set to the time of the first sample used as master // for garbage collection uint64_t time_of_last_use; // will be taken out of use if not used for a while and not in the // timing peer group - // (A member of the timing peer group could appear and disappear so will not be gc'ed.) - // for Announce Qualification - uint64_t announce_times[4]; // we'll check qualification and currency using these - uint8_t flags; // stuff related specifically to the clock itself + uint8_t flags; // stuff related specifically to the clock itself uint8_t client_flags[MAX_CLIENTS]; // stuff related to membership of the clients' timing lists // these are for finding the best clock to use @@ -97,6 +90,4 @@ void update_master_clock_info(int client_id, uint64_t master_clock_id, const cha uint64_t local_time, uint64_t local_to_master_offset, uint64_t mastership_start_time); -void debug_log_nqptp_status(int level); - #endif diff --git a/nqptp-message-handlers.c b/nqptp-message-handlers.c index 3fc8891..796e3ad 100644 --- a/nqptp-message-handlers.c +++ b/nqptp-message-handlers.c @@ -1,6 +1,6 @@ /* * This file is part of the nqptp distribution (https://github.com/mikebrady/nqptp). - * Copyright (c) 2021 Mike Brady. + * Copyright (c) 2021-2022 Mike Brady. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,7 +29,7 @@ void handle_control_port_messages(char *buf, ssize_t recv_len, clock_source_private_data *clock_private_info) { if (recv_len != -1) { buf[recv_len - 1] = 0; // make sure there's a null in it! - debug(1, "New control port message: \"%s\".", buf); + debug(2, "New control port message: \"%s\".", buf); // we need to get the client shared memory interface name from the front char *ip_list = buf; char *smi_name = strsep(&ip_list, " "); @@ -70,7 +70,7 @@ void handle_control_port_messages(char *buf, ssize_t recv_len, } } } else { - debug(2,"get or create new record for \"%s\".",smi_name); + debug(2, "get or create new record for \"%s\".", smi_name); client_id = get_client_id(smi_name); // create the record if it doesn't exist if (client_id != -1) { if (strcmp(command, "T") == 0) { @@ -126,7 +126,7 @@ void handle_control_port_messages(char *buf, ssize_t recv_len, } void handle_announce(char *buf, ssize_t recv_len, clock_source_private_data *clock_private_info, - uint64_t reception_time) { + __attribute__((unused)) uint64_t reception_time) { // only process Announce messages that do not come from self if ((clock_private_info->flags & (1 << clock_is_one_of_ours)) == 0) { // debug_print_buffer(1, buf, (size_t) recv_len); @@ -138,6 +138,7 @@ void handle_announce(char *buf, ssize_t recv_len, clock_source_private_data *clo uint64_t packet_clock_id_low = nctohl(&msg->header.clockIdentity[4]); packet_clock_id = packet_clock_id << 32; packet_clock_id = packet_clock_id + packet_clock_id_low; + clock_private_info->flags |= (1 << clock_is_announced); clock_private_info->clock_id = packet_clock_id; clock_private_info->grandmasterPriority1 = msg->announce.grandmasterPriority1; // need this for possibly pinging it later... @@ -152,144 +153,84 @@ void handle_announce(char *buf, ssize_t recv_len, clock_source_private_data *clo // it has seen three, poked the clock and doesn't want to do any more. clock_private_info->announcements_without_followups++; - int i; - // number of elements in the array is 4, hence the 4-1 stuff - for (i = 4 - 1; i > 1 - 1; i--) { - clock_private_info->announce_times[i] = clock_private_info->announce_times[i - 1]; - }; - clock_private_info->announce_times[0] = reception_time; - - // so, we have added a new element and assumed that - // now we need to walk down the array checking that non of the elements are too old - i = 0; - int valid_count = 0; - int finished = 0; - - // see 9.3.2.4.4 and 9.3.2.5 - uint64_t foreign_master_time_window = 1; - foreign_master_time_window = foreign_master_time_window - << (32 + aPTPinitialLogAnnounceInterval); - foreign_master_time_window = foreign_master_time_window * 4; - foreign_master_time_window = foreign_master_time_window >> 32; // should be 4 seconds - - uint64_t cutoff_time = reception_time + foreign_master_time_window; - int foreign_master_threshold = 2; - while ((i < 4) && (finished == 0)) { - int64_t delta = cutoff_time - clock_private_info->announce_times[i]; - if (delta > 0) - valid_count++; - else - finished = 1; - i++; + uint64_t grandmaster_clock_id = nctohl(&msg->announce.grandmasterIdentity[0]); + uint64_t grandmaster_clock_id_low = nctohl(&msg->announce.grandmasterIdentity[4]); + grandmaster_clock_id = grandmaster_clock_id << 32; + grandmaster_clock_id = grandmaster_clock_id + grandmaster_clock_id_low; + uint32_t clockQuality = ntohl(msg->announce.grandmasterClockQuality); + uint8_t clockClass = (clockQuality >> 24) & 0xff; + uint8_t clockAccuracy = (clockQuality >> 16) & 0xff; + uint16_t offsetScaledLogVariance = clockQuality & 0xffff; + uint16_t stepsRemoved = ntohs(msg->announce.stepsRemoved); + uint16_t sourcePortID = ntohs(msg->header.sourcePortID); + + // something in might have changed that + // affects its status as a possible master clock. + int best_clock_update_needed = 0; + if (clock_private_info->grandmasterIdentity != grandmaster_clock_id) { + clock_private_info->grandmasterIdentity = grandmaster_clock_id; + best_clock_update_needed = 1; + } + if (clock_private_info->grandmasterPriority1 != msg->announce.grandmasterPriority1) { + clock_private_info->grandmasterPriority1 = msg->announce.grandmasterPriority1; + best_clock_update_needed = 1; + } + if (clock_private_info->grandmasterQuality != clockQuality) { + clock_private_info->grandmasterQuality = clockQuality; + best_clock_update_needed = 1; + } + if (clock_private_info->grandmasterClass != clockClass) { + clock_private_info->grandmasterClass = clockClass; + best_clock_update_needed = 1; + } + if (clock_private_info->grandmasterAccuracy != clockAccuracy) { + clock_private_info->grandmasterAccuracy = clockAccuracy; + best_clock_update_needed = 1; + } + if (clock_private_info->grandmasterVariance != offsetScaledLogVariance) { + clock_private_info->grandmasterVariance = offsetScaledLogVariance; + best_clock_update_needed = 1; + } + if (clock_private_info->grandmasterPriority2 != msg->announce.grandmasterPriority2) { + clock_private_info->grandmasterPriority2 = msg->announce.grandmasterPriority2; + best_clock_update_needed = 1; + } + if (clock_private_info->stepsRemoved != stepsRemoved) { + clock_private_info->stepsRemoved = stepsRemoved; + best_clock_update_needed = 1; + } + if (clock_private_info->clock_port_number != sourcePortID) { + clock_private_info->clock_port_number = sourcePortID; + best_clock_update_needed = 1; } - if (valid_count >= foreign_master_threshold) { - uint64_t grandmaster_clock_id = nctohl(&msg->announce.grandmasterIdentity[0]); - uint64_t grandmaster_clock_id_low = nctohl(&msg->announce.grandmasterIdentity[4]); - grandmaster_clock_id = grandmaster_clock_id << 32; - grandmaster_clock_id = grandmaster_clock_id + grandmaster_clock_id_low; - uint32_t clockQuality = ntohl(msg->announce.grandmasterClockQuality); - uint8_t clockClass = (clockQuality >> 24) & 0xff; - uint8_t clockAccuracy = (clockQuality >> 16) & 0xff; - uint16_t offsetScaledLogVariance = clockQuality & 0xffff; - uint16_t stepsRemoved = ntohs(msg->announce.stepsRemoved); - uint16_t sourcePortID = ntohs(msg->header.sourcePortID); - int best_clock_update_needed = 0; - if (((clock_private_info->flags & (1 << clock_is_qualified)) == 0) && - (stepsRemoved < 255)) { - // if it's just becoming qualified - clock_private_info->grandmasterIdentity = grandmaster_clock_id; - clock_private_info->grandmasterPriority1 = msg->announce.grandmasterPriority1; - clock_private_info->grandmasterQuality = clockQuality; // class/accuracy/variance - clock_private_info->grandmasterClass = clockClass; - clock_private_info->grandmasterAccuracy = clockAccuracy; - clock_private_info->grandmasterVariance = offsetScaledLogVariance; - clock_private_info->grandmasterPriority2 = msg->announce.grandmasterPriority2; - clock_private_info->stepsRemoved = stepsRemoved; - clock_private_info->clock_port_number = sourcePortID; - best_clock_update_needed = 1; - } else { - // otherwise, something in it might have changed, I guess, that - // affects its status as a possible master clock. - if (clock_private_info->grandmasterIdentity != grandmaster_clock_id) { - clock_private_info->grandmasterIdentity = grandmaster_clock_id; - best_clock_update_needed = 1; - } - if (clock_private_info->grandmasterPriority1 != msg->announce.grandmasterPriority1) { - clock_private_info->grandmasterPriority1 = msg->announce.grandmasterPriority1; - best_clock_update_needed = 1; - } - if (clock_private_info->grandmasterQuality != clockQuality) { - clock_private_info->grandmasterQuality = clockQuality; - best_clock_update_needed = 1; - } - if (clock_private_info->grandmasterClass != clockClass) { - clock_private_info->grandmasterClass = clockClass; - best_clock_update_needed = 1; - } - if (clock_private_info->grandmasterAccuracy != clockAccuracy) { - clock_private_info->grandmasterAccuracy = clockAccuracy; - best_clock_update_needed = 1; - } - if (clock_private_info->grandmasterVariance != offsetScaledLogVariance) { - clock_private_info->grandmasterVariance = offsetScaledLogVariance; - best_clock_update_needed = 1; - } - if (clock_private_info->grandmasterPriority2 != msg->announce.grandmasterPriority2) { - clock_private_info->grandmasterPriority2 = msg->announce.grandmasterPriority2; - best_clock_update_needed = 1; - } - if (clock_private_info->stepsRemoved != stepsRemoved) { - clock_private_info->stepsRemoved = stepsRemoved; - best_clock_update_needed = 1; - } - } - if (best_clock_update_needed) { - debug(2, "best clock update needed"); - debug(2, - "clock_id %" PRIx64 - " at: %s, \"Announce\" message is %sQualified -- See 9.3.2.5.", - clock_private_info->clock_id, clock_private_info->ip, - clock_private_info->stepsRemoved < 255 ? "" : "not "); - debug(2, " grandmasterIdentity: %" PRIx64 ".", grandmaster_clock_id); - debug(2, " grandmasterPriority1: %u.", msg->announce.grandmasterPriority1); - debug(2, " grandmasterClockQuality: 0x%x.", clockQuality); - debug(2, " clockClass: %u.", clockClass); // See 7.6.2.4 clockClass - debug(2, " clockAccuracy: 0x%x.", - clockAccuracy); // See 7.6.2.5 clockAccuracy - debug(2, " offsetScaledLogVariance: 0x%x.", - offsetScaledLogVariance); // See 7.6.3 PTP variance - debug(2, " grandmasterPriority2: %u.", msg->announce.grandmasterPriority2); - debug(2, " stepsRemoved: %u.", stepsRemoved); - debug(2, " portNumber: %u.", sourcePortID); - - // now go and re-mark the best clock in the timing peer list - if (clock_private_info->stepsRemoved >= 255) // 9.3.2.5 (d) - clock_private_info->flags &= ~(1 << clock_is_qualified); - else - clock_private_info->flags |= (1 << clock_is_qualified); - // check/update the mastership of any clients that might be affected - int temp_client_id; - for (temp_client_id = 0; temp_client_id < MAX_CLIENTS; temp_client_id++) { - if ((clock_private_info->client_flags[temp_client_id] & - (1 << clock_is_a_timing_peer)) != 0) { - debug(2, - "best_clock_update_needed because %" PRIx64 - " on ip %s has changed -- updating clock mastership for client \"%s\"", - clock_private_info->clock_id, clock_private_info->ip, - get_client_name(temp_client_id)); - update_master(temp_client_id); - } + if (best_clock_update_needed) { + debug(2, "best clock update needed"); + debug(2, " grandmasterIdentity: %" PRIx64 ".", grandmaster_clock_id); + debug(2, " grandmasterPriority1: %u.", msg->announce.grandmasterPriority1); + debug(2, " grandmasterClockQuality: 0x%x.", clockQuality); + debug(2, " clockClass: %u.", clockClass); // See 7.6.2.4 clockClass + debug(2, " clockAccuracy: 0x%x.", + clockAccuracy); // See 7.6.2.5 clockAccuracy + debug(2, " offsetScaledLogVariance: 0x%x.", + offsetScaledLogVariance); // See 7.6.3 PTP variance + debug(2, " grandmasterPriority2: %u.", msg->announce.grandmasterPriority2); + debug(2, " stepsRemoved: %u.", stepsRemoved); + debug(2, " portNumber: %u.", sourcePortID); + + // check/update the mastership of any clients that might be affected + int temp_client_id; + for (temp_client_id = 0; temp_client_id < MAX_CLIENTS; temp_client_id++) { + if ((clock_private_info->client_flags[temp_client_id] & (1 << clock_is_a_timing_peer)) != + 0) { + debug(2, + "best_clock_update_needed because %" PRIx64 + " on ip %s has changed -- updating clock mastership for client \"%s\"", + clock_private_info->clock_id, clock_private_info->ip, + get_client_name(temp_client_id)); + update_master(temp_client_id); } } - } else { - if ((clock_private_info->flags & (1 << clock_is_qualified)) != - 0) // if it was qualified, but now isn't - debug(1, - "clock_id %" PRIx64 - " on ip: %s \"Announce\" message is not Qualified -- See 9.3.2.5.", - clock_private_info->clock_id, clock_private_info->ip); - clock_private_info->flags &= ~(1 << clock_is_qualified); } } } @@ -310,7 +251,7 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len, preciseOriginTimestamp = preciseOriginTimestamp + nanoseconds; // update our sample information - + if (clock_private_info->follow_up_number < 100) clock_private_info->follow_up_number++; @@ -320,10 +261,6 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len, debug(2, "FOLLOWUP from %" PRIx64 ", %s.", clock_private_info->clock_id, &clock_private_info->ip); uint64_t offset = preciseOriginTimestamp - reception_time; - clock_private_info->local_time = reception_time; - clock_private_info->source_time = preciseOriginTimestamp; - clock_private_info->local_to_source_time_offset = offset; - int64_t jitter = 0; int64_t time_since_previous_offset = 0; @@ -333,158 +270,77 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len, time_since_previous_offset = reception_time - clock_private_info->previous_offset_time; } -/* - int clock_is_becoming_master_somewhere = 0; - { - int temp_client_id; - for (temp_client_id = 0; temp_client_id < MAX_CLIENTS; temp_client_id++) { - if ((clock_private_info->client_flags[temp_client_id] & (1 << clock_is_becoming_master)) != - 0) { - clock_is_becoming_master_somewhere = 1; - } - } - } - if ((clock_private_info->flags & (1 << clock_is_becoming_master)) != 0) - clock_is_becoming_master_somewhere = 1; - - if (clock_is_becoming_master_somewhere != 0) { - // we now definitely have at least one sample since a request was made to - // designate this clock a master, so we assume it is legitimate. That is, we assume - // that the clock originator knows that it a clock master by now. - clock_private_info->mastership_start_time = clock_private_info->local_time; - - // designate the clock as master wherever is was becoming a master - { - int temp_client_id; - for (temp_client_id = 0; temp_client_id < MAX_CLIENTS; temp_client_id++) { - if ((clock_private_info->client_flags[temp_client_id] & (1 << clock_is_becoming_master)) != - 0) { - debug(2, - "clock_is_becoming_master %" PRIx64 - " at %s -- changing to clock_is_master for client \"%s\"", - clock_private_info->clock_id, clock_private_info->ip, - get_client_name(temp_client_id)); - clock_private_info->client_flags[temp_client_id] &= ~(1 << clock_is_becoming_master); - clock_private_info->client_flags[temp_client_id] |= (1 << clock_is_master); - } - } - } - - clock_private_info->previous_offset_time = 0; - debug_log_nqptp_status(2); - } else - - - if ((clock_private_info->previous_offset_time != 0) && - (time_since_previous_offset < 300000000000)) { - // i.e. if it's not becoming a master and there has been a previous follow_up - // i.e. if there has been a previous follow_up - int64_t time_since_last_sync = reception_time - clock_private_info->last_sync_time; - int64_t sync_timeout = 300000000000; // nanoseconds - if (clock_private_info->last_sync_time == 0) - debug(2, "Never synced."); + // Do acceptance checking and smoothing. + + // Positive changes in the offset are much more likely to be + // legitimate, since they could only occur due to a shorter + // propagation time or less of a delay sending or receiving the packet. + // (Actually, this is not quite true -- + // it is possible that the remote clock could be adjusted forward + // and this would increase the offset too.) + // Anyway, when the clock is new, we give extra preferential weighting to + // positive changes in the offset. + + // If the new offset is greater, by any amount, than the old offset, + // or if it is less by up to 10 mS, accept it. + // Otherwise, drop it if the last sample was fairly recent + // If the last sample was long ago, take this as a discontinuity and + // accept it as the start of a new period of mastership. + + // This seems to be quite stable + + if (clock_private_info->previous_offset_time != 0) + jitter = offset - clock_private_info->previous_offset; + + // We take any positive or a limited negative jitter as a sync event in + // a continuous synchronisation sequence. + // This works well with PTP sources that sleep, as when they sleep + // their clock stops. When they awaken, the offset from + // the local clock to them must be smaller than before, triggering the + // timing discontinuity below and allowing an immediate readjustment. + + // The full value of a positive offset jitter is accepted for a + // number of follow_ups at the start. + // After that, the weight of the jitter is reduced. + // Follow-ups don't always come in at 125 ms intervals, especially after a discontinuity + // Delays makes the offsets smaller than they should be, which is quickly + // allowed for. + + if ((clock_private_info->previous_offset_time != 0) && (jitter > -10000000)) { + + if (jitter < 0) { + if (clock_private_info->follow_up_number < (5 * 8)) // at the beginning (8 samples per second) + smoothed_offset = clock_private_info->previous_offset + jitter / 16; + else + smoothed_offset = clock_private_info->previous_offset + jitter / 64; + } else if (clock_private_info->follow_up_number < + (5 * 8)) // at the beginning (8 samples per second) + smoothed_offset = + clock_private_info->previous_offset + jitter / 1; // accept positive changes quickly else - debug(2, "Sync interval: %f seconds.", 0.000000001 * time_since_last_sync); - if ((clock_private_info->last_sync_time != 0) && (time_since_last_sync < sync_timeout)) { -*/ - // Do acceptance checking. - - // Positive changes in the offset are much more likely to be - // legitimate, since they could only occur due to a shorter - // propagation time. (Actually, this is not quite true -- - // it is possible that the remote clock could be adjusted forward - // and this would increase the offset too.) - // Anyway, when the clock is new, we give preferential weighting to - // positive changes in the offset. - - // If the new offset is greater, by any amount, than the old offset, - // or if it is less by up to 10 mS, - // accept it. - // Otherwise, drop it - - // This seems to be quite stable - - if (clock_private_info->previous_offset_time != 0) - jitter = offset - clock_private_info->previous_offset; - - // We take any positive or a limited negative jitter as a sync event in - // a continuous synchronisation sequence. - // This works well with PTP sources that sleep, as when they sleep - // their clock stops. When they awaken, the offset from - // the local clock to them must be a lot smaller, triggering the - // timing discontinuity below and allowing a rapid readjustment - - // The full value of positive the offset jitter is accepted for a - // number of follow_ups at the start. - // After that, the weight of the jitter is reduced. - // Follow-ups don't always come in at 125 ms intervals, especially after a discontinuity - // Delays makes the offsets smaller than they should be, which is quickly - // allowed for. - - if ((clock_private_info->previous_offset_time != 0) && (jitter > -10000000)) { - - if (jitter < 0) { - if (clock_private_info->follow_up_number < - (5 * 8)) // at the beginning (8 samples per second) - smoothed_offset = clock_private_info->previous_offset + jitter / 16; - else - smoothed_offset = clock_private_info->previous_offset + jitter / 64; - } else if (clock_private_info->follow_up_number < - (5 * 8)) // at the beginning (8 samples per second) - smoothed_offset = - clock_private_info->previous_offset + jitter / 1; // accept positive changes quickly - else - smoothed_offset = clock_private_info->previous_offset + jitter / 64; - clock_private_info->last_sync_time = reception_time; - } else { - // allow samples to disappear for up to a second - if ((time_since_previous_offset != 0) && (time_since_previous_offset < 1000000000)) { - smoothed_offset = clock_private_info->previous_offset; // if we have recent samples, forget the present sample... - } else { - if (clock_private_info->previous_offset_time == 0) - debug(1,"New clock %" PRIx64 " at %s.", clock_private_info->clock_id, clock_private_info->ip); - else - debug(1,"Timing discontinuity on clock %" PRIx64 " at %s: time_since_previous_offset: %.3f seconds.", clock_private_info->clock_id, clock_private_info->ip, 0.000000001 * time_since_previous_offset); - smoothed_offset = offset; - clock_private_info->follow_up_number = 0; - clock_private_info->mastership_start_time = - reception_time; // mastership is reset to this time... - } - } -/* + smoothed_offset = clock_private_info->previous_offset + jitter / 64; + } else { + // allow samples to disappear for up to a second + if ((time_since_previous_offset != 0) && (time_since_previous_offset < 1000000000)) { + smoothed_offset = + clock_private_info + ->previous_offset; // if we have recent samples, forget the present sample... } else { - debug(1, "Time since last sync: %.3f seconds.", 0.000000001 * time_since_last_sync); - int clock_is_a_master_somewhere = 0; - int temp_client_id; - for (temp_client_id = 0; temp_client_id < MAX_CLIENTS; temp_client_id++) { - if ((clock_private_info->client_flags[temp_client_id] & (1 << clock_is_master)) != 0) { - clock_is_a_master_somewhere = 1; - } - } - - if ((clock_is_a_master_somewhere != 0) && (clock_private_info->last_sync_time == 0)) - debug(2, "Synchronising master clock %" PRIx64 " at %s.", clock_private_info->clock_id, + if (clock_private_info->previous_offset_time == 0) + debug(2, "New clock %" PRIx64 " at %s.", clock_private_info->clock_id, clock_private_info->ip); - if ((clock_is_a_master_somewhere != 0) && (clock_private_info->last_sync_time != 0)) - debug(1, "Resynchronising master clock %" PRIx64 " at %s.", clock_private_info->clock_id, - clock_private_info->ip); - // leave the offset as it was coming in and take it as a sync time - clock_private_info->last_sync_time = reception_time; - clock_private_info->mastership_start_time = - reception_time; // mastership is reset to this time... - clock_private_info->previous_offset_time = 0; - } - } else { - clock_private_info->last_sync_time = reception_time; - if (time_since_previous_offset >= 300000000000) { - debug(1, "Long interval: %f seconds since previous follow_up", - time_since_previous_offset * 1E-9); + else + debug(2, + "Timing discontinuity on clock %" PRIx64 + " at %s: time_since_previous_offset: %.3f seconds.", + clock_private_info->clock_id, clock_private_info->ip, + 0.000000001 * time_since_previous_offset); + smoothed_offset = offset; + clock_private_info->follow_up_number = 0; clock_private_info->mastership_start_time = reception_time; // mastership is reset to this time... - clock_private_info->previous_offset_time = 0; } } -*/ clock_private_info->previous_offset = smoothed_offset; clock_private_info->previous_offset_time = reception_time; @@ -494,10 +350,15 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len, if ((clock_private_info->client_flags[temp_client_id] & (1 << clock_is_master)) != 0) { debug(2, "clock_is_master -- updating master clock info for client \"%s\"", get_client_name(temp_client_id)); - debug(1, "Clock %" PRIx64 " at %s. Offset: %" PRIx64 ", smoothed offset: %" PRIx64 ". Precise Origin Timestamp: %" PRIx64 ". Time since previous offset: %.3f milliseconds.", clock_private_info->clock_id, clock_private_info->ip, offset, smoothed_offset, preciseOriginTimestamp, 0.000001 * time_since_previous_offset); + debug(2, + "Clock %" PRIx64 " at %s. Offset: %" PRIx64 ", smoothed offset: %" PRIx64 + ". Precise Origin Timestamp: %" PRIx64 + ". Time since previous offset: %.3f milliseconds.", + clock_private_info->clock_id, clock_private_info->ip, offset, smoothed_offset, + preciseOriginTimestamp, 0.000001 * time_since_previous_offset); update_master_clock_info(temp_client_id, clock_private_info->clock_id, - (const char *)&clock_private_info->ip, reception_time, smoothed_offset, - clock_private_info->mastership_start_time); + (const char *)&clock_private_info->ip, reception_time, + smoothed_offset, clock_private_info->mastership_start_time); } } } -- 2.47.2