]> git.ipfire.org Git - thirdparty/nqptp.git/commitdiff
not using new/update stuff any more -- this migrated into SPS.
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Tue, 13 Apr 2021 14:22:33 +0000 (15:22 +0100)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Tue, 13 Apr 2021 14:22:33 +0000 (15:22 +0100)
nqptp-clock-sources.c
nqptp-clock-sources.h
nqptp-message-handlers.c
nqptp-shm-structures.h
nqptp.c
nqptp.h

index cc97b7125fd63b99afda1e33d6cecb92797e375d..7a97db739f68bc5816d7bfdf5ec030be8f9dc7bd 100644 (file)
@@ -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
index 631c7fce990cff76870ced02bc9e6bbed239312d..3521366ba0cea9d2a2217e24410bf6dc91462e2c 100644 (file)
@@ -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
index 4aa9b61f8f6165546c3ca024a4805e6ce84c8f88..715153919b98f2c14acf52e8ee230ff98f62273f 100644 (file)
 #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!");
index 4c41118373c2030073ec339bf23e667538c18158..7cadb7f2a6a64e5810c9812d6f0538bf3ed059f6 100644 (file)
 
 #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 024c681d462b47fde399dea777634499dc1afda6..f037b8350f7602e0f65b2992d3517725565c0f28 100644 (file)
--- a/nqptp.c
+++ b/nqptp.c
 #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 93c2a107876a15d2ae22f07139ac45d695a98239..0cdd68cec24c9e76f03b79407d6785a186c8017a 100644 (file)
--- a/nqptp.h
+++ b/nqptp.h
 
 #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