]> git.ipfire.org Git - thirdparty/nqptp.git/commitdiff
Move the Sync hander into the message-handlers, add a function to generate a self...
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Thu, 8 Apr 2021 16:33:19 +0000 (17:33 +0100)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Thu, 8 Apr 2021 16:33:19 +0000 (17:33 +0100)
nqptp-clock-sources.h
nqptp-message-handlers.c
nqptp-message-handlers.h
nqptp-utilities.c
nqptp-utilities.h
nqptp.c

index 6f46172bab6fc6436ca4c9d6deed2150efc03118..a35d3e1f49d1226ddafe5618118155ae7b31bd02 100644 (file)
@@ -28,7 +28,7 @@ enum stage {
   sync_seen,
 };
 
-#define MAX_TIMING_SAMPLES 19
+#define MAX_TIMING_SAMPLES 3
 typedef struct {
   uint64_t local, local_to_remote_offset;
 } timing_samples;
@@ -50,6 +50,7 @@ typedef struct {
   int vacant_samples; // the number of elements in the timing_samples array that are not yet used
   int next_sample_goes_here; // point to where in the timing samples array the next entries should
                              // go
+  uint32_t sample_number;
 } clock_source_private_data;
 
 int find_clock_source_record(char *sender_string, clock_source *clocks_shared_info,
index add262f06c45cf18074cfc754b8c7327a6937861..ab112932036c54dabfbf7ecca740797a5eb9c297 100644 (file)
@@ -50,6 +50,7 @@ void handle_control_port_messages(char *buf, ssize_t recv_len, clock_source *clo
           // if it is just about to become a timing peer, reset its sample count
           clock_private_info[t].vacant_samples = MAX_TIMING_SAMPLES;
           clock_private_info[t].next_sample_goes_here = 0;
+          clock_private_info[t].sample_number = 0;
           clock_info[t].flags |= (1 << clock_is_a_timing_peer);
         }
       }
@@ -190,7 +191,8 @@ void handle_follow_up(char *buf, ssize_t recv_len, clock_source *clock_info,
     // now, if there was a valid offset previously,
     // check if the offset should be clamped
 
-    if ((clock_info->flags & (1 << clock_is_valid)) &&
+    // don't clamp for the first two seconds?
+    if ((clock_info->flags & (1 << clock_is_valid)) && (clock_private_info->sample_number > 17) &&
         (clock_private_info->vacant_samples != MAX_TIMING_SAMPLES)) {
 
       const int64_t clamp = 1 * 1000 * 1000;
@@ -212,6 +214,7 @@ void handle_follow_up(char *buf, ssize_t recv_len, clock_source *clock_info,
     clock_private_info->samples[clock_private_info->next_sample_goes_here].local_to_remote_offset =
         offset;
     clock_private_info->next_sample_goes_here++;
+    clock_private_info->sample_number++;
     if (clock_private_info->next_sample_goes_here == MAX_TIMING_SAMPLES)
       clock_private_info->next_sample_goes_here = 0;
     if (clock_private_info->vacant_samples == MAX_TIMING_SAMPLES) {
@@ -269,4 +272,61 @@ void handle_follow_up(char *buf, ssize_t recv_len, clock_source *clock_info,
           ntohs(msg->header.sequenceId), sync_seen, clock_private_info->current_stage,
           clock_private_info->sequence_number, clock_info->ip);
   }
-}
\ No newline at end of file
+}
+
+void handle_sync(char *buf, ssize_t recv_len, clock_source *clock_info,
+                 clock_source_private_data *clock_private_info, uint64_t reception_time) {
+
+  struct ptp_sync_message *msg = (struct ptp_sync_message *)buf;
+  // this is just to see if anything interesting comes in the SYNC package
+  // a non-zero origin timestamp
+  // or correction field would be interesting....
+  int ck;
+  int non_empty_origin_timestamp = 0;
+  for (ck = 0; ck < 10; ck++) {
+    if (msg->sync.originTimestamp[ck] != 0) {
+      non_empty_origin_timestamp = (non_empty_origin_timestamp | 1);
+    }
+  }
+  if (non_empty_origin_timestamp != 0)
+    debug(2, "Sync Origin Timestamp!");
+  if (msg->header.correctionField != 0)
+    debug(3, "correctionField: %" PRIx64 ".", msg->header.correctionField);
+
+  int discard_sync = 0;
+
+  // check if we should discard this SYNC
+  if (clock_private_info->current_stage != waiting_for_sync) {
+
+    // here, we have an unexpected SYNC. It could be because the
+    // previous transaction sequence failed for some reason
+    // But, if that is so, the SYNC will have a newer sequence number
+    // so, ignore it if it's a little older.
+
+    // If it seems a lot older in sequence number terms, then it might
+    // be the start of a completely new sequence, so if the
+    // difference is more than 40 (WAG), accept it
+
+    uint16_t new_sync_sequence_number = ntohs(msg->header.sequenceId);
+    int16_t sequence_number_difference =
+        (clock_private_info->sequence_number - new_sync_sequence_number);
+
+    if ((sequence_number_difference > 0) && (sequence_number_difference < 40))
+      discard_sync = 1;
+  }
+
+  if (discard_sync == 0) {
+
+    clock_private_info->sequence_number = ntohs(msg->header.sequenceId);
+    clock_private_info->t2 = reception_time;
+
+    // it turns out that we don't really need to send a Delay_Req
+    // as a Follow_Up message always comes through
+
+    // If we had hardware assisted network timing, then maybe
+    // Even then, AP2 devices don't seem to send an accurate
+    // Delay_Resp time -- it contains the same information as the Follow_Up
+
+    clock_private_info->current_stage = sync_seen;
+  }
+}
index 056e7544998ee481e7eca8ca24674b9023e50e49..4460c95e8dd4a238a65ed187e9bebb03b7c1c35e 100644 (file)
@@ -26,6 +26,9 @@
 void handle_announce(char *buf, ssize_t recv_len, clock_source *clock_info,
                      clock_source_private_data *clock_private_info, uint64_t reception_time);
 
+void handle_sync(char *buf, ssize_t recv_len, clock_source *clock_info,
+                 clock_source_private_data *clock_private_info, uint64_t reception_time);
+
 void handle_follow_up(char *buf, ssize_t recv_len, clock_source *clock_info,
                       clock_source_private_data *clock_private_info, uint64_t reception_time,
                       pthread_mutex_t *shm_mutex);
index 201bc7da5abc8168827e5a12b855fd3ccd55a678..3b98b45ca482f70323a1f1368450781f9a525f96 100644 (file)
@@ -21,6 +21,8 @@
 #include "general-utilities.h"
 #include <errno.h>
 #include <fcntl.h>
+#include <ifaddrs.h>
+#include <linux/if_packet.h>
 #include <linux/net_tstamp.h>
 #include <netdb.h>
 #include <stdio.h>
@@ -165,3 +167,41 @@ void debug_print_buffer(int level, char *buf, size_t buf_len) {
     free(obf);
   }
 }
+
+uint64_t get_self_clock_id() {
+  // make up a clock ID based on an interfaces' MAC
+  char local_clock_id[8];
+  int len = 0;
+  struct ifaddrs *ifaddr = NULL;
+  struct ifaddrs *ifa = NULL;
+  int status;
+  if ((status = getifaddrs(&ifaddr) == -1)) {
+    die("getifaddrs: %s", gai_strerror(status));
+  } else {
+    int found = 0;
+    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+      if ((ifa->ifa_addr) && (ifa->ifa_addr->sa_family == AF_PACKET)) {
+        struct sockaddr_ll *s = (struct sockaddr_ll *)ifa->ifa_addr;
+        if ((strcmp(ifa->ifa_name, "lo") != 0) && (found == 0)) {
+          len = s->sll_halen;
+          memcpy(local_clock_id, &s->sll_addr, len);
+          found = 1;
+        }
+      }
+    }
+    freeifaddrs(ifaddr);
+  }
+  // if the length of the MAC address is 6 we need to doctor it a little
+  // See Section 7.5.2.2.2 IEEE EUI-64 clockIdentity values, NOTE 2
+
+  if (len == 6) { // i.e. an EUI-48 MAC Address
+    local_clock_id[7] = local_clock_id[5];
+    local_clock_id[6] = local_clock_id[4];
+    local_clock_id[5] = local_clock_id[3];
+    local_clock_id[3] = 0xFF;
+    local_clock_id[4] = 0xFE;
+  }
+  uint64_t result;
+  memcpy(&result, local_clock_id, sizeof(result));
+  return result;
+}
index 9e07c6142311b3545e471181b930dcbb5ed56539..f821f281903d5e412fe3b35d1b40fb2f6dc28cc1 100644 (file)
@@ -36,5 +36,6 @@ typedef struct {
 
 void open_sockets_at_port(uint16_t port, sockets_open_bundle *sockets_open_stuff);
 void debug_print_buffer(int level, char *buf, size_t buf_len);
+uint64_t get_self_clock_id(); // a clock ID based on a MAC address
 
 #endif
\ No newline at end of file
diff --git a/nqptp.c b/nqptp.c
index 6a2e2477479ec60f08aad77ee4b2f9b7a4eca74b..0828436738dbde7ac908fc4dd97902af68008a36 100644 (file)
--- a/nqptp.c
+++ b/nqptp.c
@@ -349,58 +349,8 @@ int main(void) {
                                   &clocks_private[the_clock], reception_time);
                   break;
                 case Sync: { // if it's a sync
-                  struct ptp_sync_message *msg = (struct ptp_sync_message *)buf;
-                  // this is just to see if anything interesting comes in the SYNC package
-                  // a non-zero origin timestamp
-                  // or correction field would be interesting....
-                  int ck;
-                  int non_empty_origin_timestamp = 0;
-                  for (ck = 0; ck < 10; ck++) {
-                    if (msg->sync.originTimestamp[ck] != 0) {
-                      non_empty_origin_timestamp = (non_empty_origin_timestamp | 1);
-                    }
-                  }
-                  if (non_empty_origin_timestamp != 0)
-                    debug(2, "Sync Origin Timestamp!");
-                  if (msg->header.correctionField != 0)
-                    debug(3, "correctionField: %" PRIx64 ".", msg->header.correctionField);
-
-                  int discard_sync = 0;
-
-                  // check if we should discard this SYNC
-                  if (clocks_private[the_clock].current_stage != waiting_for_sync) {
-
-                    // here, we have an unexpected SYNC. It could be because the
-                    // previous transaction sequence failed for some reason
-                    // But, if that is so, the SYNC will have a newer sequence number
-                    // so, ignore it if it's a little older.
-
-                    // If it seems a lot older in sequence number terms, then it might
-                    // be the start of a completely new sequence, so if the
-                    // difference is more than 40 (WAG), accept it
-
-                    uint16_t new_sync_sequence_number = ntohs(msg->header.sequenceId);
-                    int16_t sequence_number_difference =
-                        (clocks_private[the_clock].sequence_number - new_sync_sequence_number);
-
-                    if ((sequence_number_difference > 0) && (sequence_number_difference < 40))
-                      discard_sync = 1;
-                  }
-
-                  if (discard_sync == 0) {
-
-                    clocks_private[the_clock].sequence_number = ntohs(msg->header.sequenceId);
-                    clocks_private[the_clock].t2 = reception_time;
-
-                    // it turns out that we don't really need to send a Delay_Req
-                    // as a Follow_Up message always comes through
-
-                    // If we had hardware assisted network timing, then maybe
-                    // Even then, AP2 devices don't seem to send an accurate
-                    // Delay_Resp time -- it contains the same information is the Follow_Up
-
-                    clocks_private[the_clock].current_stage = sync_seen;
-                  }
+                  handle_sync(buf, recv_len, &shared_memory->clocks[the_clock],
+                              &clocks_private[the_clock], reception_time);
                 } break;
 
                 case Follow_Up: {