]> git.ipfire.org Git - thirdparty/nqptp.git/commitdiff
Send a faux announcment message to every timing peer. This seems to reawaken the...
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Mon, 1 Nov 2021 17:40:45 +0000 (17:40 +0000)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Mon, 1 Nov 2021 17:40:45 +0000 (17:40 +0000)
nqptp-clock-sources.c
nqptp-clock-sources.h
nqptp-message-handlers.c
nqptp.c
nqptp.h

index 9128c67ca7f9fd35a03e355cd7e7811cc1579b0f..0300639551e2e6fd365f830617e68dbe81a8579d 100644 (file)
 #include <arpa/inet.h>
 #include <errno.h>
 #include <ifaddrs.h>
+#include <netdb.h>
 #include <string.h>
-#include <sys/types.h>
 #include <sys/socket.h>
-#include <netdb.h>
+#include <sys/types.h>
 
 #ifdef CONFIG_FOR_FREEBSD
 #include <netinet/in.h>
@@ -74,7 +74,7 @@ int create_clock_source_record(char *sender_string,
   if (found == 1) {
     int family = 0;
 
-  // check its ipv4/6 family -- derived froom https://stackoverflow.com/a/3736377, with thanks.
+    // check its ipv4/6 family -- derived from https://stackoverflow.com/a/3736377, with thanks.
     struct addrinfo hint, *res = NULL;
     memset(&hint, '\0', sizeof hint);
     hint.ai_family = PF_UNSPEC;
@@ -89,7 +89,8 @@ int create_clock_source_record(char *sender_string,
       clocks_private_info[i].family = family;
       clocks_private_info[i].vacant_samples = MAX_TIMING_SAMPLES;
       clocks_private_info[i].in_use = 1;
-      debug(1, "create record for ip: %s, family: %s.", &clocks_private_info[i].ip, clocks_private_info[i].family == AF_INET6 ? "IPv6" : "IPv4");
+      debug(2, "create record for ip: %s, family: %s.", &clocks_private_info[i].ip,
+            clocks_private_info[i].family == AF_INET6 ? "IPv6" : "IPv4");
     } else {
       die("cannot getaddrinfo for ip: %s.", &clocks_private_info[i].ip);
     }
@@ -123,6 +124,8 @@ 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();
+        else
+          debug_log_nqptp_status(1);
       }
     }
   }
@@ -186,8 +189,8 @@ void debug_log_nqptp_status(int level) {
   for (i = 0; i < MAX_CLOCKS; i++)
     if (clocks_private[i].in_use != 0)
       records_in_use++;
+  debug(level, "");
   if (records_in_use > 0) {
-    debug(level, "");
     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);
@@ -220,6 +223,8 @@ void debug_log_nqptp_status(int level) {
         }
       }
     }
+  } else {
+    debug(level, "Current NQPTP Status: no records in use.");
   }
 }
 
index 1a8cd66f02835858307ff86bf146847d0f301674..53b1bce1e94a81d1b4ac7e397dd34bae04777bc8 100644 (file)
@@ -41,8 +41,10 @@ typedef struct {
 
 // information about each clock source
 typedef struct {
-  char ip[64]; // 64 is nicely aligned and bigger than INET6_ADDRSTRLEN (46)
-  int family; // AF_INET or AF_INET6
+  char ip[64];            // 64 is nicely aligned and bigger than INET6_ADDRSTRLEN (46)
+  int family;             // AF_INET or AF_INET6
+  int announcements_sent; // number of announce messages returned to this clock
+  int followup_seen;      // set to true when a followup has come from this clock
   uint64_t clock_id;
   uint64_t local_time; // the local time when the offset was calculated
   uint64_t source_time;
index e3f150990032f2fdab36cf4a196ece98e5f35213..39e6dc6d2bc4057bbd35b0051efe8282626ce6e2 100644 (file)
@@ -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 timing peer list: \"%s\".", buf);
+    debug(2, "New timing peer list: \"%s\".", buf);
     if (buf[0] == 'T') {
 
       char *ip_list = buf + 1;
@@ -51,6 +51,8 @@ void handle_control_port_messages(char *buf, ssize_t recv_len,
           if (t == -1)
             t = create_clock_source_record(new_ip, clock_private_info);
           clock_private_info[t].flags |= (1 << clock_is_a_timing_peer);
+          clock_private_info[t].announcements_sent = 0;
+          clock_private_info[t].followup_seen = 0; // no followup seen while a timing peer
         }
       }
 
@@ -63,9 +65,6 @@ void handle_control_port_messages(char *buf, ssize_t recv_len,
           debug(2, "%s.", &clock_private_info[i].ip);
       }
       debug(2, "Timing group end");
-
-      announce_messages_sent_to_timing_peers = 0;
-
     } else {
       warn("Unrecognised string on the control port.");
     }
@@ -89,6 +88,9 @@ void handle_announce(char *buf, ssize_t recv_len, clock_source_private_data *clo
       packet_clock_id = packet_clock_id + packet_clock_id_low;
       clock_private_info->clock_id = packet_clock_id;
 
+      debug(2, "announcement seen from %" PRIx64 " at %s.", clock_private_info->clock_id,
+            clock_private_info->ip);
+
       int i;
       // number of elements in the array is 4, hence the 4-1 stuff
       for (i = 4 - 1; i > 1 - 1; i--) {
@@ -132,7 +134,7 @@ void handle_announce(char *buf, ssize_t recv_len, clock_source_private_data *clo
         uint16_t sourcePortID = ntohs(msg->header.sourcePortID);
         int best_clock_update_needed = 0;
         if (((clock_private_info->flags & (1 << clock_is_qualified)) == 0) &&
-            (msg->announce.stepsRemoved < 255)) {
+            (stepsRemoved < 255)) {
           // if it's just becoming qualified
           clock_private_info->grandmasterIdentity = grandmaster_clock_id;
           clock_private_info->grandmasterPriority1 = msg->announce.grandmasterPriority1;
@@ -223,7 +225,6 @@ void handle_announce(char *buf, ssize_t recv_len, clock_source_private_data *clo
 void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len,
                       clock_source_private_data *clock_private_info, uint64_t reception_time) {
 
-  clock_private_info->flags |= (1 << clock_is_valid); // valid because it has at least one follow_up
   struct ptp_follow_up_message *msg = (struct ptp_follow_up_message *)buf;
 
   uint16_t seconds_hi = nctohs(&msg->follow_up.preciseOriginTimestamp[0]);
@@ -237,6 +238,9 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len,
 
   // update our sample information
 
+  clock_private_info->followup_seen =
+      1; // say we've seen a follow_up -- suppresses announcements_sent
+
   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 =
@@ -347,6 +351,7 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len,
     clock_private_info->flags &= ~(1 << clock_is_becoming_master);
     clock_private_info->flags |= 1 << clock_is_master;
     clock_private_info->previous_offset_time = 0;
+    debug_log_nqptp_status(1);
   } else if (clock_private_info->previous_offset_time != 0) {
     // i.e. if it's not becoming a master and there has been a previous follow_up
     int64_t time_since_last_sync = reception_time - clock_private_info->last_sync_time;
@@ -393,6 +398,9 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len,
     clock_private_info->last_sync_time = reception_time;
   }
 
+  clock_private_info->previous_offset = offset;
+  clock_private_info->previous_offset_time = reception_time;
+
   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,
                              reception_time, offset, clock_private_info->mastership_start_time);
@@ -400,6 +408,11 @@ void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len,
           clock_private_info->clock_id, reception_time, offset, 0.000001 * jitter);
   }
 
-  clock_private_info->previous_offset = offset;
-  clock_private_info->previous_offset_time = reception_time;
+  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();
+  }
 }
diff --git a/nqptp.c b/nqptp.c
index 1faa345b8a3538e19f5f288cbe5ed1c438ddb740..3de752548fc39e63fdbb3c6db1acb988d66b207a 100644 (file)
--- a/nqptp.c
+++ b/nqptp.c
@@ -61,8 +61,6 @@
 
 #define BUFLEN 4096 // Max length of buffer
 
-int announce_messages_sent_to_timing_peers; // used to stop sending Announce messages
-
 sockets_open_bundle sockets_open_stuff;
 
 int master_clock_index = -1;
@@ -429,72 +427,72 @@ uint64_t broadcasting_task(uint64_t call_time, __attribute__((unused)) void *pri
       //      (1 << clock_is_qualified) | (1 << clock_is_a_timing_peer) | (1 << clock_is_valid);
       //       (1 << clock_is_a_timing_peer) | (1 << clock_is_valid);
       (1 << clock_is_a_timing_peer);
-  if (announce_messages_sent_to_timing_peers < 3) {
-    announce_messages_sent_to_timing_peers++;
-    for (i = 0; i < MAX_CLOCKS; i++) {
-      if ((clocks_private[i].flags & acceptance_mask) == acceptance_mask) {
-
-        // create the message
-        struct ptp_announce_message msg;
-        memset((void *)&msg, 0, sizeof(msg));
-        uint64_t my_clock_id = get_self_clock_id();
-        msg.header.transportSpecificAndMessageID = 0x10 + Announce;
-        msg.header.reservedAndVersionPTP = 0x02;
-        msg.header.messageLength = htons(sizeof(struct ptp_announce_message));
-        msg.header.flags = htons(0x0408);
-        hcton64(my_clock_id, &msg.header.clockIdentity[0]);
-        msg.header.sourcePortID = htons(32776);
-        msg.header.controlOtherMessage = 0x05;
-        msg.header.logMessagePeriod = 0xFE;
-        msg.announce.currentUtcOffset = htons(37);
-        hcton64(my_clock_id, &msg.announce.grandmasterIdentity[0]);
-        uint32_t my_clock_quality = 0xf8fe436a;
-        msg.announce.grandmasterClockQuality = htonl(my_clock_quality);
-        msg.announce.grandmasterPriority1 = 248;
-        msg.announce.grandmasterPriority2 = 248;
-        msg.announce.timeSource = 160;
-        // show it
-        // debug_print_buffer(1, (char *)&msg, sizeof(struct ptp_announce_message));
-        // get the socket for the correct port -- 320 -- and family -- IPv4 or IPv6 -- to send it
-        // from.
-
-        int s = 0;
-        unsigned t;
-        for (t = 0; t < sockets_open_stuff.sockets_open; t++) {
-          if ((sockets_open_stuff.sockets[t].port == 320) &&
-              (sockets_open_stuff.sockets[t].family == clocks_private[i].family))
-            s = sockets_open_stuff.sockets[t].number;
-        }
-        if (s == 0) {
-          debug(1, "sending socket not found!");
+  for (i = 0; i < MAX_CLOCKS; i++) {
+    if (((clocks_private[i].flags & acceptance_mask) == acceptance_mask) &&
+        (clocks_private[i].is_one_of_ours == 0) && (clocks_private[i].announcements_sent < 1) &&
+        (clocks_private[i].followup_seen == 0)) {
+
+      // create the message
+      struct ptp_announce_message msg;
+      memset((void *)&msg, 0, sizeof(msg));
+      uint64_t my_clock_id = get_self_clock_id();
+      msg.header.transportSpecificAndMessageID = 0x10 + Announce;
+      msg.header.reservedAndVersionPTP = 0x02;
+      msg.header.messageLength = htons(sizeof(struct ptp_announce_message));
+      msg.header.flags = htons(0x0408);
+      hcton64(my_clock_id, &msg.header.clockIdentity[0]);
+      msg.header.sourcePortID = htons(32776);
+      msg.header.controlOtherMessage = 0x05;
+      msg.header.logMessagePeriod = 0xFE;
+      msg.announce.currentUtcOffset = htons(37);
+      hcton64(my_clock_id, &msg.announce.grandmasterIdentity[0]);
+      uint32_t my_clock_quality = 0xf8fe436a;
+      msg.announce.grandmasterClockQuality = htonl(my_clock_quality);
+      msg.announce.grandmasterPriority1 = 100;
+      msg.announce.grandmasterPriority2 = 248;
+      msg.announce.timeSource = 160;
+      // show it
+      // debug_print_buffer(1, (char *)&msg, sizeof(struct ptp_announce_message));
+      // get the socket for the correct port -- 320 -- and family -- IPv4 or IPv6 -- to send it
+      // from.
+
+      int s = 0;
+      unsigned t;
+      for (t = 0; t < sockets_open_stuff.sockets_open; t++) {
+        if ((sockets_open_stuff.sockets[t].port == 320) &&
+            (sockets_open_stuff.sockets[t].family == clocks_private[i].family))
+          s = sockets_open_stuff.sockets[t].number;
+      }
+      if (s == 0) {
+        debug(1, "sending socket not found!");
+      } else {
+        // debug(1, "Send message from socket %d.", s);
+
+        const char *portname = "320";
+        struct addrinfo hints;
+        memset(&hints, 0, sizeof(hints));
+        hints.ai_family = AF_UNSPEC;
+        hints.ai_socktype = SOCK_DGRAM;
+        hints.ai_protocol = 0;
+        hints.ai_flags = AI_ADDRCONFIG;
+        struct addrinfo *res = NULL;
+        int err = getaddrinfo(clocks_private[i].ip, portname, &hints, &res);
+        if (err != 0) {
+          debug(1, "failed to resolve remote socket address (err=%d)", err);
         } else {
-          // debug(1, "Send message from socket %d.", s);
-
-          const char *portname = "320";
-          struct addrinfo hints;
-          memset(&hints, 0, sizeof(hints));
-          hints.ai_family = AF_UNSPEC;
-          hints.ai_socktype = SOCK_DGRAM;
-          hints.ai_protocol = 0;
-          hints.ai_flags = AI_ADDRCONFIG;
-          struct addrinfo *res = NULL;
-          int err = getaddrinfo(clocks_private[i].ip, portname, &hints, &res);
-          if (err != 0) {
-            debug(1, "failed to resolve remote socket address (err=%d)", err);
-          } else {
-            // here, we have the destination, so send it
-
-            // if (clocks_private[i].family == AF_INET6) {
-            debug(1, "message clock \"%" PRIx64 "\" at %s on %s, iteration: %d.",
-                  clocks_private[i].clock_id, clocks_private[i].ip,
-                  clocks_private[i].family == AF_INET6 ? "IPv6" : "IPv4",
-                  announce_messages_sent_to_timing_peers);
-            int ret = sendto(s, &msg, sizeof(msg), 0, res->ai_addr, res->ai_addrlen);
-            if (ret == -1)
-              debug(1, "result of sendto is %d.", ret);
-            // }
-            freeaddrinfo(res);
-          }
+          // here, we have the destination, so send it
+
+          // if (clocks_private[i].family == AF_INET6) {
+          int ret = sendto(s, &msg, sizeof(msg), 0, res->ai_addr, res->ai_addrlen);
+          if (ret == -1)
+            debug(1, "result of sendto is %d.", ret);
+          clocks_private[i].announcements_sent++;
+          debug(2, "message clock \"%" PRIx64 "\" at %s on %s, iteration: %d.",
+                clocks_private[i].clock_id, clocks_private[i].ip,
+                clocks_private[i].family == AF_INET6 ? "IPv6" : "IPv4",
+                clocks_private[i].announcements_sent);
+          // }
+          freeaddrinfo(res);
         }
       }
     }
@@ -504,6 +502,6 @@ uint64_t broadcasting_task(uint64_t call_time, __attribute__((unused)) void *pri
   announce_interval = announce_interval << (8 + aPTPinitialLogAnnounceInterval);
   announce_interval = announce_interval * 1000000000;
   announce_interval = announce_interval >> 8; // nanoseconds
-  return call_time + 250000000;
+  return call_time + 1000000000;
   // return call_time + announce_interval;
 }
diff --git a/nqptp.h b/nqptp.h
index 0c91097da9a06ba3da9090acb793267fbfb64dc2..327aba921add22eaf95cbdaf35125fda5fa93a8a 100644 (file)
--- a/nqptp.h
+++ b/nqptp.h
@@ -31,7 +31,6 @@
 // group becomes the master and its native time becomes the "master time".
 // This is what is provided to the client.
 
-extern int announce_messages_sent_to_timing_peers; // used to stop sending Announce messages
 extern int master_clock_index;
 extern struct shm_structure *shared_memory;