]> git.ipfire.org Git - thirdparty/nqptp.git/commitdiff
old and new system sort-of work now...
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Tue, 28 Dec 2021 10:56:26 +0000 (10:56 +0000)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Tue, 28 Dec 2021 10:56:26 +0000 (10:56 +0000)
nqptp-clock-sources.c
nqptp-clock-sources.h
nqptp-message-handlers.c
nqptp.c
nqptp.h

index ede9f3da4e6cd5c1f05e102a085076ccfc92aae8..ee4bcbef33cca46f17bc3e9822e282ff32ed7ebe 100644 (file)
@@ -61,6 +61,14 @@ int find_client_id(char *client_shared_memory_interface_name) {
   return response;
 }
 
+const char *get_client_name(int client_id) {
+  if ((client_id >= 0) && (client_id < MAX_CLIENTS)) {
+    return clients[client_id].shm_interface_name;
+  } else {
+    return "";
+  }
+}
+
 int get_client_id(char *client_shared_memory_interface_name) {
   int response = -1; // signify not found
   if (client_shared_memory_interface_name != NULL) {
@@ -228,9 +236,6 @@ int create_clock_source_record(char *sender_string,
       strncpy((char *)&clocks_private_info[i].ip, sender_string,
               FIELD_SIZEOF(clock_source_private_data, ip) - 1);
       clocks_private_info[i].family = family;
-#ifdef MAX_TIMING_SAMPLES
-      clocks_private_info[i].vacant_samples = MAX_TIMING_SAMPLES;
-#endif
       clocks_private_info[i].flags |= (1 << clock_is_in_use);
       debug(2, "create record for ip: %s, family: %s.", &clocks_private_info[i].ip,
             clocks_private_info[i].family == AF_INET6 ? "IPv6" : "IPv4");
@@ -250,25 +255,36 @@ void manage_clock_sources(uint64_t reception_time, clock_source_private_data *cl
   // do a garbage collect for clock records no longer in use
   for (i = 0; i < MAX_CLOCKS; i++) {
     // only if its in use and not a timing peer... don't need a mutex to check
-    if (((clocks_private_info[i].flags & (1 << clock_is_in_use)) != 0) &&
-        ((clocks_private_info[i].flags & (1 << clock_is_a_timing_peer)) == 0)) {
-      int64_t time_since_last_use = reception_time - clocks_private_info[i].time_of_last_use;
-      // using a sync timeout to determine when to drop the record...
-      // the following give the sync receipt time in whole seconds
-      // depending on the aPTPinitialLogSyncInterval and the aPTPsyncReceiptTimeout
-      int64_t syncTimeout = (1 << (32 + aPTPinitialLogSyncInterval));
-      syncTimeout = syncTimeout * aPTPsyncReceiptTimeout;
-      syncTimeout = syncTimeout >> 32;
-      // seconds to nanoseconds
-      syncTimeout = syncTimeout * 1000000000;
-      if (time_since_last_use > syncTimeout) {
-        uint32_t old_flags = clocks_private_info[i].flags;
-        debug(2, "delete record for: %s.", &clocks_private_info[i].ip);
-        memset(&clocks_private_info[i], 0, sizeof(clock_source_private_data));
-        if (old_flags != 0)
-          update_master(0); // TODO
-        else
-          debug_log_nqptp_status(2);
+    // TODO -- check all clients to see if it's in use
+    if ((clocks_private_info[i].flags & (1 << clock_is_in_use)) != 0) {
+      int clock_is_a_timing_peer_somewhere = 0;
+      int temp_client_id;
+      for (temp_client_id = 0; temp_client_id < MAX_CLIENTS; temp_client_id++) {
+        if ((clocks_private_info[i].client_flags[temp_client_id] & (1 << clock_is_a_timing_peer)) !=
+            0) {
+          clock_is_a_timing_peer_somewhere = 1;
+        }
+      }
+      if (clock_is_a_timing_peer_somewhere == 0) {
+        int64_t time_since_last_use = reception_time - clocks_private_info[i].time_of_last_use;
+        // using a sync timeout to determine when to drop the record...
+        // the following give the sync receipt time in whole seconds
+        // depending on the aPTPinitialLogSyncInterval and the aPTPsyncReceiptTimeout
+        int64_t syncTimeout = (1 << (32 + aPTPinitialLogSyncInterval));
+        syncTimeout = syncTimeout * aPTPsyncReceiptTimeout;
+        syncTimeout = syncTimeout >> 32;
+        // seconds to nanoseconds
+        syncTimeout = syncTimeout * 1000000000;
+        if (time_since_last_use > syncTimeout) {
+          uint32_t old_flags = clocks_private_info[i].flags;
+          debug(2, "delete record for: %s.", &clocks_private_info[i].ip);
+          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);
+          }
+        }
       }
     }
   }
@@ -327,6 +343,7 @@ void update_clock_self_identifications(clock_source_private_data *clocks_private
 }
 
 void debug_log_nqptp_status(int level) {
+/*
   int records_in_use = 0;
   int i;
   for (i = 0; i < MAX_CLOCKS; i++)
@@ -369,6 +386,7 @@ void debug_log_nqptp_status(int level) {
   } else {
     debug(level, "Current NQPTP Status: no records in use.");
   }
+*/
 }
 
 int uint32_cmp(uint32_t a, uint32_t b, const char *cause) {
@@ -398,7 +416,7 @@ int uint64_cmp(uint64_t a, uint64_t b, const char *cause) {
   }
 }
 
-void update_master(int client_id) {
+void old_update_master() {
 
   // This implements the IEEE 1588-2008 best master clock algorithm.
 
@@ -433,7 +451,8 @@ void update_master(int client_id) {
   int best_so_far = -1;
   int timing_peer_count = 0;
   uint32_t acceptance_mask =
-      (1 << clock_is_qualified) | (1 << clock_is_a_timing_peer) | (1 << clock_is_valid);
+//      (1 << clock_is_qualified) | (1 << clock_is_a_timing_peer) | (1 << clock_is_valid);
+      (1 << clock_is_qualified) | (1 << clock_is_a_timing_peer);
   for (i = 0; i < MAX_CLOCKS; i++) {
     if ((clocks_private[i].flags & acceptance_mask) == acceptance_mask) {
       // found a possible clock candidate
@@ -498,7 +517,7 @@ void update_master(int client_id) {
     // if (old_master != -1) {
     // but there was a master clock, so remove it
     debug(1, "Remove master clock.");
-    update_master_clock_info(0, NULL, 0, 0, 0);
+    update_master_clock_info(0, 0, NULL, 0, 0, 0);
     //}
     if (timing_peer_count == 0)
       debug(2, "no valid qualified clocks ");
@@ -517,3 +536,177 @@ void update_master(int client_id) {
   }
   debug_log_nqptp_status(2);
 }
+
+void update_master(int client_id) {
+  old_update_master(); // TODO -- for compatibility
+
+  // This implements the IEEE 1588-2008 best master clock algorithm.
+
+  // However, since nqptp is not a ptp clock, some of it doesn't apply.
+  // Specifically, the Identity of Receiver stuff doesn't apply, since the
+  // program is merely monitoring Announce message data and isn't a PTP clock itself
+  // and thus does not have any kind or receiver identity itself.
+
+  // Clock information coming from the same clock over IPv4 and IPv6 should have different
+  // port numbers.
+
+  // Figure 28 can be therefore be simplified considerably:
+
+  // Since nqptp can not be a receiver, and since nqptp can not originate a clock
+  // (and anyway nqptp filters out packets coming from self)
+  // we can do a single comparison of stepsRemoved and pick the shorter, if any.
+
+  // Figure 28 reduces to checking steps removed and then, if necessary, checking identities.
+  // If we see two identical sets of information, it is an error,
+  // but we leave things as they are.
+  int old_master = -1;
+  // find the current master clock if there is one and turn off all mastership
+  int i;
+  for (i = 0; i < MAX_CLOCKS; i++) {
+    if ((clocks_private[i].client_flags[client_id] & (1 << clock_is_master)) != 0)
+      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 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) ==
+         clock_specific_acceptance_mask) &&
+        ((clocks_private[i].client_flags[client_id] & client_specific_acceptance_mask) ==
+         client_specific_acceptance_mask)) {
+      // found a possible clock candidate
+      timing_peer_count++;
+      int outcome;
+      if (best_so_far == -1) {
+        best_so_far = i;
+      } else {
+        // Do the data set comparison detailed in Figure 27 and Figure 28 on pp89-90
+        if (clocks_private[i].grandmasterIdentity ==
+            clocks_private[best_so_far].grandmasterIdentity) {
+          // Do the relevant part of Figure 28:
+          outcome = uint32_cmp(clocks_private[i].stepsRemoved,
+                               clocks_private[best_so_far].stepsRemoved, "steps removed");
+          // we need to check the portIdentify, which is the clock_id and the clock_port_number
+          if (outcome == 0)
+            outcome = uint64_cmp(clocks_private[i].clock_id, clocks_private[best_so_far].clock_id,
+                                 "clock id");
+          if (outcome == 0)
+            outcome =
+                uint32_cmp(clocks_private[i].clock_port_number,
+                           clocks_private[best_so_far].clock_port_number, "clock port number");
+          if (outcome == 0) {
+            debug(1,
+                  "Best Master Clock algorithm: two separate but identical potential clock "
+                  "masters: %" PRIx64 ".",
+                  clocks_private[best_so_far].clock_id);
+          }
+
+        } else {
+          outcome =
+              uint32_cmp(clocks_private[i].grandmasterPriority1,
+                         clocks_private[best_so_far].grandmasterPriority1, "grandmasterPriority1");
+          if (outcome == 0)
+            outcome = uint32_cmp(clocks_private[i].grandmasterClass,
+                                 clocks_private[best_so_far].grandmasterClass, "grandmasterClass");
+          if (outcome == 0)
+            outcome =
+                uint32_cmp(clocks_private[i].grandmasterAccuracy,
+                           clocks_private[best_so_far].grandmasterAccuracy, "grandmasterAccuracy");
+          if (outcome == 0)
+            outcome =
+                uint32_cmp(clocks_private[i].grandmasterVariance,
+                           clocks_private[best_so_far].grandmasterVariance, "grandmasterVariance");
+          if (outcome == 0)
+            outcome = uint32_cmp(clocks_private[i].grandmasterPriority2,
+                                 clocks_private[best_so_far].grandmasterPriority2,
+                                 "grandmasterPriority2");
+          if (outcome == 0)
+            // this can't fail, as it's a condition of entering this section that they are different
+            outcome =
+                uint64_cmp(clocks_private[i].grandmasterIdentity,
+                           clocks_private[best_so_far].grandmasterIdentity, "grandmasterIdentity");
+        }
+        if (outcome == -1)
+          best_so_far = i;
+      }
+    }
+  }
+  if (best_so_far == -1) {
+    // no master clock
+    // if (old_master != -1) {
+    // but there was a master clock, so remove it
+    debug(1, "Remove master clock.");
+    update_master_clock_info(client_id, 0, NULL, 0, 0, 0);
+    //}
+    if (timing_peer_count == 0)
+      debug(2, "no valid qualified clocks ");
+    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_becoming_master);
+        // clocks_private[best_so_far].flags |= (1 << clock_is_becoming_master); // to avoid searching        
+      } else {
+        clocks_private[best_so_far].client_flags[client_id] |= (1 << clock_is_master);      
+        // the smi will be updated when the next followup occurs
+      }
+    } else {
+      // if it's the same one as before
+      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,
+                              uint64_t local_time, uint64_t local_to_master_offset,
+                              uint64_t mastership_start_time) {
+  // for compatibility
+  old_update_master_clock_info(master_clock_id, ip, local_time, local_to_master_offset,
+                               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!");
+    clients[client_id].shared_memory->master_clock_id = master_clock_id;
+    if (ip != NULL) {
+      strncpy((char *)&clients[client_id].shared_memory->master_clock_ip, ip,
+              FIELD_SIZEOF(struct shm_structure, master_clock_ip) - 1);
+      clients[client_id].shared_memory->master_clock_start_time = mastership_start_time;
+      clients[client_id].shared_memory->local_time = local_time;
+      clients[client_id].shared_memory->local_to_master_time_offset = local_to_master_offset;
+    } else {
+      clients[client_id].shared_memory->master_clock_ip[0] = '\0';
+      clients[client_id].shared_memory->master_clock_start_time = 0;
+      clients[client_id].shared_memory->local_time = 0;
+      clients[client_id].shared_memory->local_to_master_time_offset = 0;
+    }
+    rc = pthread_mutex_unlock(&clients[client_id].shared_memory->shm_mutex);
+    if (rc != 0)
+      warn("Can't release mutex after updating master clock!");
+    // debug(1,"update_master_clock_info done");
+  }
+}
index 7b666aa81323f5f4e9698397995bd7d87ea58640..d98e1532747935e5e42a9f24fd1df056e301656b 100644 (file)
@@ -25,7 +25,7 @@
 typedef enum {
   clock_is_in_use,
   clock_is_one_of_ours,
-  clock_is_valid,
+//  clock_is_valid,
   clock_is_a_timing_peer,
   clock_is_qualified,
   clock_is_becoming_master,
@@ -94,15 +94,18 @@ void update_clock_self_identifications(clock_source_private_data *clocks_private
 void manage_clock_sources(uint64_t reception_time, clock_source_private_data *clocks_private_info);
 
 int find_client_id(char *client_shared_memory_interface_name);
-
 int get_client_id(char *client_shared_memory_interface_name);
-
+const char *get_client_name(int id);
 int delete_clients();
 
 extern clock_source_private_data clocks_private[MAX_CLOCKS];
 
 void update_master(int client_id);
 
+void update_master_clock_info(int client_id, uint64_t master_clock_id, const char *ip,
+                              uint64_t local_time, uint64_t local_to_master_offset,
+                              uint64_t mastership_start_time);
+
 void debug_log_nqptp_status(int level);
 
 #endif
index a1be6ed65f2141fc18d94423252498407b327366..292ea9a3835f1527ae40c4b5d514dc359260fbbc 100644 (file)
@@ -266,7 +266,17 @@ void handle_announce(char *buf, ssize_t recv_len, clock_source_private_data *clo
             clock_private_info->flags &= ~(1 << clock_is_qualified);
           else
             clock_private_info->flags |= (1 << clock_is_qualified);
-          update_master(0); // TODO -- use client_id here
+          // 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(1, "clock_is_qualified -- updating clock mastership for client \"%s\"",
+                    get_client_name(temp_client_id));
+              update_master(temp_client_id);
+            }
+          }
+          update_master(0); // TODO -- won't be needed
         }
       } else {
         if ((clock_private_info->flags & (1 << clock_is_qualified)) !=
@@ -301,21 +311,6 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len,
 
   clock_private_info->announcements_without_followups = 0; // we've seen a followup
 
-#ifdef MAX_TIMING_SAMPLES
-  clock_private_info->samples[clock_private_info->next_sample_goes_here].local_time =
-      reception_time;
-  clock_private_info->samples[clock_private_info->next_sample_goes_here].clock_time =
-      preciseOriginTimestamp;
-
-  if (clock_private_info->vacant_samples > 0)
-    clock_private_info->vacant_samples--;
-
-  clock_private_info->next_sample_goes_here++;
-  // if we have need to wrap.
-  if (clock_private_info->next_sample_goes_here == MAX_TIMING_SAMPLES)
-    clock_private_info->next_sample_goes_here = 0;
-#endif
-
   debug(2, "FOLLOWUP from %" PRIx64 ", %s.", clock_private_info->clock_id, &clock_private_info->ip);
   uint64_t offset = preciseOriginTimestamp - reception_time;
 
@@ -331,95 +326,40 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len,
     time_since_previous_offset = reception_time - clock_private_info->previous_offset_time;
   }
 
-  if ((clock_private_info->flags & (1 << clock_is_becoming_master)) != 0) {
-    // we definitely have at least one sample since the request was made to
-    // designate it a master, so we assume it is legitimate. That is, we assume
-    // that the clock originator knows that it a clock master by now.
-#ifdef MAX_TIMING_SAMPLES
-    uint64_t oldest_acceptable_master_clock_time =
-        clock_private_info->source_time + 1150000000; // ns.
-
-    // we will try to improve on this present, definitive, local_to_source_time_offset we have
-    int changes_made = 0;
-
-    uint64_t best_offset_so_far = clock_private_info->local_to_source_time_offset;
-    uint64_t age_of_oldest_legitimate_sample = clock_private_info->local_time;
-
-    int number_of_samples = MAX_TIMING_SAMPLES - clock_private_info->vacant_samples;
-    int samples_checked = 0;
-    if (number_of_samples > 0) {
-      debug(3, "Number of samples: %d.", number_of_samples);
-
-      // Now we use the last few samples to calculate the best offset for the
-      // new master clock.
-
-      // The time of the oldest sample we use will become the time of the start of the
-      // mastership.
-
-      // We will accept samples that would make the local-to-clock offset greatest,
-      // provided they are not too old and that they don't push the current clock time
-      // more than, say, 1000 ms plus one sample interval (i.e about 1.125 seconds) in the future.
-
-      // This present sample is the only time estimate we have when the clock is definitely a
-      // master, so we use it to eliminate any previous time estimates, made when the clock wasn't
-      // designated a master, that would put it more than, say, a 1.15 seconds further into the
-      // future.
-
-      // Allow the samples to give a valid master clock time up to this much later than the
-      // present, definitive, sample:
-
-      uint64_t oldest_acceptable_time = reception_time - 10000000000; // only go back this far (ns)
-
-      int64_t cko = age_of_oldest_legitimate_sample - oldest_acceptable_time;
-      if (cko < 0)
-        debug(1, "starting sample is too old: %" PRId64 " ns.", cko);
-
-      int i;
-      for (i = 0; i < number_of_samples; i++) {
-        int64_t age = reception_time - clock_private_info->samples[i].local_time;
-        int64_t age_relative_to_oldest_acceptable_time =
-            clock_private_info->samples[i].local_time - oldest_acceptable_time;
-        if (age_relative_to_oldest_acceptable_time > 0) {
-          debug(3, "sample accepted at %f seconds old.", 0.000000001 * age);
-          if (clock_private_info->samples[i].local_time < age_of_oldest_legitimate_sample) {
-            age_of_oldest_legitimate_sample = clock_private_info->samples[i].local_time;
-          }
-          uint64_t possible_offset =
-              clock_private_info->samples[i].clock_time - clock_private_info->samples[i].local_time;
-          uint64_t possible_master_clock_time = clock_private_info->local_time + possible_offset;
-          int64_t age_relative_to_oldest_acceptable_master_clock_time =
-              possible_master_clock_time - oldest_acceptable_master_clock_time;
-          if (age_relative_to_oldest_acceptable_master_clock_time <= 0) {
-            samples_checked++;
-            // so, the sample was not obtained too far in the past
-            // and it would not push the estimated master clock_time too far into the future
-            // so, if it is greater than the best_offset_so_far, then make it the new one
-            if (possible_offset > best_offset_so_far) {
-              debug(3, "new best offset");
-              best_offset_so_far = possible_offset;
-              changes_made++;
-            }
-          } else {
-            debug(3, "sample too far into the future");
+      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;
           }
-        } else {
-          debug(3, "sample too old at %f seconds old.", 0.000000001 * age);
         }
       }
-    }
-    clock_private_info->mastership_start_time = age_of_oldest_legitimate_sample;
-    int64_t offset_difference =
-        best_offset_so_far - clock_private_info->local_to_source_time_offset;
-    debug(2, "Lookback difference: %f ms with %d samples checked of %d samples total.",
-          0.000001 * offset_difference, samples_checked, number_of_samples);
-    clock_private_info->local_to_source_time_offset = best_offset_so_far;
-    debug(2, "Master sampling started %f ms before becoming master.",
-          0.000001 * (reception_time - age_of_oldest_legitimate_sample));
-#else
+      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;
-#endif
-    clock_private_info->flags &= ~(1 << clock_is_becoming_master);
-    clock_private_info->flags |= 1 << clock_is_master;
+    
+    // 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(1, "clock_is_becoming_master -- updating to clock_is_master for client \"%s\"",
+                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->flags &= ~(1 << clock_is_becoming_master); // won't need this
+    clock_private_info->flags |= 1 << clock_is_master; // won't need this
     clock_private_info->previous_offset_time = 0;
     debug_log_nqptp_status(2);
   } else if ((clock_private_info->previous_offset_time != 0) &&
@@ -468,7 +408,16 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len,
         offset = clock_private_info->previous_offset; // forget the present sample...
       }
     } else {
-      if ((clock_private_info->flags & (1 << clock_is_master)) != 0)
+      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)
         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
@@ -491,18 +440,39 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len,
   clock_private_info->previous_offset = offset;
   clock_private_info->previous_offset_time = reception_time;
 
+  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) {
+      debug(1, "clock_is_master -- updating master clock info for client \"%s\"",
+            get_client_name(temp_client_id));
+      update_master_clock_info(temp_client_id, clock_private_info->clock_id,
+                               (const char *)&clock_private_info->ip, reception_time, offset,
+                               clock_private_info->mastership_start_time);
+    }
+  }
+
+  // TODO -- remove the following when we are done
   if ((clock_private_info->flags & (1 << clock_is_master)) != 0) {
-    update_master_clock_info(clock_private_info->clock_id, (const char *)&clock_private_info->ip,
+    update_master_clock_info(0, clock_private_info->clock_id, (const char *)&clock_private_info->ip,
                              reception_time, offset, clock_private_info->mastership_start_time);
     debug(3, "clock: %" PRIx64 ", time: %" PRIu64 ", offset: %" PRId64 ", jitter: %+f ms.",
           clock_private_info->clock_id, reception_time, offset, 0.000001 * jitter);
   }
-
+  /*
   if ((clock_private_info->flags & (1 << clock_is_valid)) == 0) {
     debug(2, "follow_up seen from %" PRIx64 " at %s.", clock_private_info->clock_id,
           clock_private_info->ip);
     clock_private_info->flags |=
         (1 << clock_is_valid); // valid because it has at least one follow_up
-    update_master(0);          // TODO
+
+    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(1, "clock_is_valid has become true -- updating clock mastership for client \"%s\"",
+              get_client_name(temp_client_id));
+        update_master(temp_client_id);
+      }
+    }
+    update_master(0); // TODO -- won't be needed
   }
+  */
 }
diff --git a/nqptp.c b/nqptp.c
index e58280c924fe53c4dd829ea058a8c476d657d48a..3984c06bf464a02af00b9af8f23ccc64dce02d20 100644 (file)
--- a/nqptp.c
+++ b/nqptp.c
@@ -85,8 +85,8 @@ uint64_t sample_task(uint64_t call_time, __attribute__((unused)) void *private_d
 struct shm_structure *shared_memory = NULL; // this is where public clock info is available
 int epoll_fd;
 
-void update_master_clock_info(uint64_t master_clock_id, const char *ip, uint64_t local_time,
-                              uint64_t local_to_master_offset, uint64_t mastership_start_time) {
+void old_update_master_clock_info(uint64_t master_clock_id, const char *ip, uint64_t local_time,
+                                  uint64_t local_to_master_offset, uint64_t mastership_start_time) {
 
   // debug(1,"update_master_clock_info start");
   if (shared_memory->master_clock_id != master_clock_id)
diff --git a/nqptp.h b/nqptp.h
index f86c968933eb167f9069e7b699fe043eee13a8a9..b2f9d4e5e63af825c8ad9eec034eb84f70d15ba8 100644 (file)
--- a/nqptp.h
+++ b/nqptp.h
@@ -40,7 +40,7 @@
 // Instances" -- of a "PTP Network" it wishes to monitor. This is a "timing group" in AirPlay 2
 // parlance, it seems.
 
-void update_master_clock_info(uint64_t master_clock_id, const char *ip, uint64_t local_time,
-                              uint64_t local_to_master_offset, uint64_t mastership_start_time);
+void old_update_master_clock_info(uint64_t master_clock_id, const char *ip, uint64_t local_time,
+                                  uint64_t local_to_master_offset, uint64_t mastership_start_time);
 
 #endif