From 73164f4fe89bac2c0361016c5eb3aa10abd89d1a Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Mon, 1 Nov 2021 17:40:45 +0000 Subject: [PATCH] Send a faux announcment message to every timing peer. This seems to reawaken the PTP system in an Apple Silicon Mac. --- nqptp-clock-sources.c | 15 +++-- nqptp-clock-sources.h | 6 +- nqptp-message-handlers.c | 29 ++++++--- nqptp.c | 134 +++++++++++++++++++-------------------- nqptp.h | 1 - 5 files changed, 101 insertions(+), 84 deletions(-) diff --git a/nqptp-clock-sources.c b/nqptp-clock-sources.c index 9128c67..0300639 100644 --- a/nqptp-clock-sources.c +++ b/nqptp-clock-sources.c @@ -24,10 +24,10 @@ #include #include #include +#include #include -#include #include -#include +#include #ifdef CONFIG_FOR_FREEBSD #include @@ -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."); } } diff --git a/nqptp-clock-sources.h b/nqptp-clock-sources.h index 1a8cd66..53b1bce 100644 --- a/nqptp-clock-sources.h +++ b/nqptp-clock-sources.h @@ -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; diff --git a/nqptp-message-handlers.c b/nqptp-message-handlers.c index e3f1509..39e6dc6 100644 --- a/nqptp-message-handlers.c +++ b/nqptp-message-handlers.c @@ -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 1faa345..3de7525 100644 --- 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 0c91097..327aba9 100644 --- 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; -- 2.47.2