From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Tue, 13 Apr 2021 14:22:33 +0000 (+0100) Subject: not using new/update stuff any more -- this migrated into SPS. X-Git-Tag: 1.1-dev~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=339e00f642e4d510b073e30de75c8d69a53a8125;p=thirdparty%2Fnqptp.git not using new/update stuff any more -- this migrated into SPS. --- diff --git a/nqptp-clock-sources.c b/nqptp-clock-sources.c index cc97b71..7a97db7 100644 --- a/nqptp-clock-sources.c +++ b/nqptp-clock-sources.c @@ -29,6 +29,8 @@ #define FIELD_SIZEOF(t, f) (sizeof(((t *)0)->f)) #endif +clock_source_private_data clocks_private[MAX_CLOCKS]; + int find_clock_source_record(char *sender_string, clock_source *clocks_shared_info, clock_source_private_data *clocks_private_info) { // return the index of the clock in the clock information arrays or -1 diff --git a/nqptp-clock-sources.h b/nqptp-clock-sources.h index 631c7fc..3521366 100644 --- a/nqptp-clock-sources.h +++ b/nqptp-clock-sources.h @@ -78,4 +78,6 @@ void update_clock_self_identifications(clock_source *clocks_shared_info, void manage_clock_sources(uint64_t reception_time, clock_source *clocks_shared_info, clock_source_private_data *clocks_private_info); +extern clock_source_private_data clocks_private[MAX_CLOCKS]; + #endif diff --git a/nqptp-message-handlers.c b/nqptp-message-handlers.c index 4aa9b61..7151539 100644 --- a/nqptp-message-handlers.c +++ b/nqptp-message-handlers.c @@ -24,11 +24,25 @@ #include "debug.h" #include "general-utilities.h" -void mark_best_clock(clock_source *clock_info, clock_source_private_data *clock_private_info) { +void update_master_old(int do_reset, clock_source *clock_info, clock_source_private_data *clock_private_info) { + debug(2,"set new master with do_reset of: %s.", do_reset == 0 ? "false" : "true"); + // do_reset is true if you want to discard existing PTP timing + + int old_master = -1; + + int i; + for (i = 0; i < MAX_CLOCKS; i++) { + if ((clock_info[i].flags & (1 << clock_is_master)) != 0) + if (old_master == -1) + old_master = i; // find old master + clock_info[i].flags &= ~(1 << clock_is_master); // turn them all off + } + + if ((do_reset == 0) && (old_master == -1)) + debug(1,"can't find previous master during update"); + int best_so_far = -1; int timing_peer_count = 0; - int i = 0; - uint32_t acceptance_mask = (1 << clock_is_valid) | (1 << clock_is_qualified) | (1 << clock_is_a_timing_peer); for (i = 0; i < MAX_CLOCKS; i++) { @@ -65,33 +79,67 @@ void mark_best_clock(clock_source *clock_info, clock_source_private_data *clock_ } } if (best_so_far != -1) { - debug(2, "best clock is %" PRIx64 ".", clock_info[best_so_far].clock_id); - for (i = 0; i < MAX_CLOCKS; i++) { - if (i == best_so_far) - clock_info[i].flags |= (1 << clock_is_best); - else - clock_info[i].flags &= ~(1 << clock_is_best); + // we found a master clock + clock_info[best_so_far].flags |= (1 << clock_is_master); + // master_clock_index = best_so_far; + if (do_reset) { + master_clock_to_ptp_offset = 0; + } else if (old_master != best_so_far) { + // we need to calculate new offset for the new clock + //debug(1,"old master %d, new master: %d", old_master, best_so_far); + //debug(1,"existing clock offset: %" PRIx64 ".", clock_info[old_master].local_to_source_time_offset); + //debug(1,"existing ptp offset: %" PRIx64 ".", master_clock_to_ptp_offset); + //debug(1,"new clock offset: %" PRIx64 ".", clock_info[best_so_far].local_to_source_time_offset); + + uint64_t existing_total_offset = clock_info[old_master].local_to_source_time_offset + master_clock_to_ptp_offset; + master_clock_to_ptp_offset = existing_total_offset - clock_info[best_so_far].local_to_source_time_offset; + } + if ((do_reset) || (old_master != best_so_far)) { + debug(1, "master clock index is: %d, local_to_master_clock_to_ptp_offset is %" PRIx64 " ID is: %" PRIx64 ".", best_so_far, master_clock_to_ptp_offset, clock_info[best_so_far].clock_id); + } else { + debug(2, "master clock index is unchanged: %d, master_clock_to_ptp_offset is %" PRIx64 " ID is: %" PRIx64 ".", best_so_far, master_clock_to_ptp_offset, clock_info[best_so_far].clock_id); } } else { - if (timing_peer_count != 0) - debug(1, "best clock not found!"); + if (timing_peer_count == 0) + debug(1, "no timing peer list"); + else + debug(1, "master clock not found!"); + } + + for (i = 0; i < MAX_CLOCKS; i++) { + if ((clock_info[i].flags & (1 << clock_is_master)) != 0) + debug(2,"leaving with %d as master", i); } + +} + +void update_master(int do_reset) { + update_master_old(do_reset, &shared_memory->clocks, clocks_private); } void handle_control_port_messages(char *buf, ssize_t recv_len, clock_source *clock_info, clock_source_private_data *clock_private_info) { if (recv_len != -1) { buf[recv_len - 1] = 0; // make sure there's a null in it! - if (strstr(buf, "set_timing_peers ") == buf) { - char *ip_list = buf + strlen("set_timing_peers "); + if ((buf[0] == new_timing_peer_list) || (buf[0] == update_timing_peer_list)){ + debug(1,"Received a new timing peer list message: \"%s\".", buf); + + char *ip_list = buf + 1; + if (*ip_list == ' ') + ip_list++; + + int do_reset = 0; + if (buf[0] == 'N') + do_reset = 1; int rc = pthread_mutex_lock(&shared_memory->shm_mutex); if (rc != 0) - warn("Can't acquire mutex to set_timing_peers!"); - // turn off all is_timing_peers + warn("Can't acquire mutex to set timing peers!"); + // turn off all is_timing_peer int i; - for (i = 0; i < MAX_CLOCKS; i++) - clock_info[i].flags &= ~(1 << clock_is_a_timing_peer); // turn off peer flags + for (i = 0; i < MAX_CLOCKS; i++) { + clock_info[i].flags &= ~(1 << clock_is_a_timing_peer); // turn off peer flag (but not the master flag!) + } while (ip_list != NULL) { char *new_ip = strsep(&ip_list, " "); @@ -110,11 +158,13 @@ void handle_control_port_messages(char *buf, ssize_t recv_len, clock_source *clo } } - // now go and mark the best clock in the timing peer list - mark_best_clock(clock_info, clock_private_info); + // now find and mark the best clock in the timing peer list as the master + update_master(do_reset); rc = pthread_mutex_unlock(&shared_memory->shm_mutex); + + if (rc != 0) - warn("Can't release mutex after set_timing_peers!"); + warn("Can't release mutex after set timing peers!"); debug(2, "Timing group start"); for (i = 0; i < MAX_CLOCKS; i++) { if ((clock_info[i].flags & (1 << clock_is_a_timing_peer)) != 0) @@ -253,7 +303,7 @@ void handle_announce(char *buf, ssize_t recv_len, clock_source *clock_info, clock_info->flags &= ~(1 << clock_is_qualified); else clock_info->flags |= (1 << clock_is_qualified); - mark_best_clock(clock_info, clock_private_info); + update_master(0); // 0 means do update, not reset if (pthread_mutex_unlock(&shared_memory->shm_mutex) != 0) warn("Can't release mutex after marking best clock!"); } @@ -265,10 +315,10 @@ void handle_announce(char *buf, ssize_t recv_len, clock_source *clock_info, " on ip: %s \"Announce\" message is not Qualified -- See 9.3.2.5.", clock_info->clock_id, clock_info->ip); if (pthread_mutex_lock(&shared_memory->shm_mutex) != 0) - warn("Can't acquire mutex to set_timing_peers!"); + warn("Can't acquire mutex to mark unqualified clock!"); clock_info->flags &= ~(1 << clock_is_qualified); if (pthread_mutex_unlock(&shared_memory->shm_mutex) != 0) - warn("Can't release mutex after set_timing_peers!"); + warn("Can't release mutex after marking unqualified clock!"); } } } @@ -514,6 +564,15 @@ void handle_follow_up(char *buf, ssize_t recv_len, clock_source *clock_info, clock_info->flags |= (1 << clock_is_valid); clock_info->local_time = clock_private_info->t2; clock_info->local_to_source_time_offset = estimated_offset; + + if ((clock_info->flags & (1 << clock_is_master)) != 0) { + shared_memory->master_clock_id = clock_info->clock_id; + shared_memory->local_time = clock_info->local_time; + uint64_t new_ptp_offset = clock_info->local_to_source_time_offset; + new_ptp_offset += master_clock_to_ptp_offset; + shared_memory->local_to_ptp_time_offset = new_ptp_offset; + debug(1,"clock: %" PRIx64 ", local_to_ptp_time_offset: %" PRIx64 ", master_clock_to_ptp_offset: % " PRIx64 ".", shared_memory->master_clock_id, new_ptp_offset, master_clock_to_ptp_offset); + } rc = pthread_mutex_unlock(shm_mutex); if (rc != 0) warn("Can't release mutex after updating a clock!"); diff --git a/nqptp-shm-structures.h b/nqptp-shm-structures.h index 4c41118..7cadb7f 100644 --- a/nqptp-shm-structures.h +++ b/nqptp-shm-structures.h @@ -22,11 +22,11 @@ #define STORAGE_ID "/nqptp" #define MAX_CLOCKS 32 -#define NQPTP_SHM_STRUCTURES_VERSION 1 +#define NQPTP_SHM_STRUCTURES_VERSION 2 #define NQPTP_CONTROL_PORT 9000 -// the control port will accept a packet with the first word being: -// "set_timing_peers" followed by a space and then a space-delimited +// the control port will accept a packet with the first letter being: +// "N" or "U" followed by a space and then a space-delimited // list of ip numbers, either IPv4 or IPv6 // the whole not to exceed 4096 characters in total @@ -41,9 +41,14 @@ typedef enum { clock_is_valid, clock_is_a_timing_peer, clock_is_qualified, - clock_is_best + clock_is_master } clock_flags; +typedef enum { + new_timing_peer_list = 'N', // followed by a (possibly empty) space-separated list of IPs + update_timing_peer_list = 'U' +} control_port_command; + typedef struct { char ip[64]; // 64 is nicely aligned and bigger than INET6_ADDRSTRLEN (46) uint64_t clock_id; @@ -54,10 +59,13 @@ typedef struct { struct shm_structure { pthread_mutex_t shm_mutex; // for safely accessing the structure - uint16_t size_of_clock_array; // check this is equal to MAX_SHARED_CLOCKS - uint16_t version; // check this is equal to NQPTP_SHM_STRUCTURES_VERSION - uint32_t flags; - clock_source clocks[MAX_CLOCKS]; + uint16_t size_of_clock_array; // deprecated -- check this is equal to MAX_SHARED_CLOCKS + uint16_t version; // deprecated -- check this is equal to NQPTP_SHM_STRUCTURES_VERSION + uint32_t flags; // unused + uint64_t local_time; // the time when the offset was calculated + uint64_t local_to_ptp_time_offset; // add this to the local time to get PTP time + uint64_t clock_id; // for information only + clock_source clocks[MAX_CLOCKS]; // deprecated }; #endif diff --git a/nqptp.c b/nqptp.c index 024c681..f037b83 100644 --- a/nqptp.c +++ b/nqptp.c @@ -69,7 +69,10 @@ #define MAX_EVENTS 128 // For epoll sockets_open_bundle sockets_open_stuff; -clock_source_private_data clocks_private[MAX_CLOCKS]; + +int master_clock_index = -1; +uint64_t master_clock_to_ptp_offset; + struct shm_structure *shared_memory = NULL; // this is where public clock info is available int epoll_fd; diff --git a/nqptp.h b/nqptp.h index 93c2a10..0cdd68c 100644 --- a/nqptp.h +++ b/nqptp.h @@ -24,6 +24,27 @@ #define MAX_OPEN_SOCKETS 16 + +// When a new timing peer group is created, one of the clocks in the +// group becomes the master and its "native" time becomes the clock's "PTP time". +// This is what is provided to the client. + +// If another clock becomes the new master, then its "native" time will +// generally be different from PTP time. +// The offset from the new master's time to PTP time +// will be added to the master's time to translate it to PTP time. + +// You can create a _new_ timing peer group, which starts with a zero +// master_clock_to_ptp_offset and thus sets the PTP time to the native time +// of the first clock master of the group, as nature intended. + +// Alternatively, you can _update_ an existing timing peer group, which calculates an +// appropriate master_clock_to_ptp_offset to preserve timing relative to +// the existing PTP time, ensuring that PTP time remain consistent even +// when the clock master changes. + +extern int master_clock_index; +extern uint64_t master_clock_to_ptp_offset; extern struct shm_structure *shared_memory; #endif \ No newline at end of file