}
}
-void handle_follow_up(char *buf, __attribute__((unused)) ssize_t recv_len,
- clock_source_private_data *clock_private_info, uint64_t reception_time) {
-
- struct ptp_follow_up_message *msg = (struct ptp_follow_up_message *)buf;
-
- uint16_t seconds_hi = nctohs(&msg->follow_up.preciseOriginTimestamp[0]);
- uint32_t seconds_low = nctohl(&msg->follow_up.preciseOriginTimestamp[2]);
- uint32_t nanoseconds = nctohl(&msg->follow_up.preciseOriginTimestamp[6]);
- uint64_t preciseOriginTimestamp = seconds_hi;
- preciseOriginTimestamp = preciseOriginTimestamp << 32;
- preciseOriginTimestamp = preciseOriginTimestamp + seconds_low;
- preciseOriginTimestamp = preciseOriginTimestamp * 1000000000L;
- preciseOriginTimestamp = preciseOriginTimestamp + nanoseconds;
-
- // update our sample information
-
- if (clock_private_info->follow_up_number < 100)
- clock_private_info->follow_up_number++;
-
- if (clock_private_info->announcements_without_followups < 4) // if we haven't signalled already
- clock_private_info->announcements_without_followups = 0; // we've seen a followup
-
- debug(2, "FOLLOWUP from %" PRIx64 ", %s.", clock_private_info->clock_id, &clock_private_info->ip);
- uint64_t offset = preciseOriginTimestamp - reception_time;
-
- int64_t jitter = 0;
-
- int64_t time_since_previous_offset = 0;
- uint64_t smoothed_offset = offset;
-
- // This is a bit hacky.
- // Basically, the idea is that if the grandmaster has changed, then acceptance checking and smoothing
- // should start as it it's a new clock. This is because the preciseOriginTimestamp, which is part of
- // the data that is being smoothed, refers to the grandmaster, so when the grandmaster changes
- // any previous calculations are no longer valid.
- // The hacky bit is to signal this condition by zeroing the previous_offset_time.
- if (clock_private_info->previous_offset_grandmaster != clock_private_info->grandmasterIdentity)
- clock_private_info->previous_offset_time = 0; // the preciseOriginTimestamp always (?) refers to the grandmaster
-
- if (clock_private_info->previous_offset_time != 0) {
- time_since_previous_offset = reception_time - clock_private_info->previous_offset_time;
- }
-
- // Do acceptance checking and smoothing.
-
- // Positive changes in the offset are much more likely to be
- // legitimate, since they could only occur due to a shorter
- // propagation time or less of a delay sending or receiving the packet.
- // (Actually, this is not quite true --
- // it is possible that the remote clock could be adjusted forward
- // and this would increase the offset too.)
- // Anyway, when the clock is new, we give extra preferential weighting to
- // positive changes in the offset.
-
- // If the new offset is greater, by any amount, than the old offset,
- // or if it is less by up to 10 mS, accept it.
- // Otherwise, drop it if the last sample was fairly recent
- // If the last sample was long ago, take this as a discontinuity and
- // accept it as the start of a new period of mastership.
-
- // This seems to be quite stable
-
- if (clock_private_info->previous_offset_time != 0)
- jitter = offset - clock_private_info->previous_offset;
-
- // We take any positive or a limited negative jitter as a sync event in
- // a continuous synchronisation sequence.
- // This works well with PTP sources that sleep, as when they sleep
- // their clock stops. When they awaken, the offset from
- // the local clock to them must be smaller than before, triggering the
- // timing discontinuity below and allowing an immediate readjustment.
-
- // The full value of a positive offset jitter is accepted for a
- // number of follow_ups at the start.
- // After that, the weight of the jitter is reduced.
- // Follow-ups don't always come in at 125 ms intervals, especially after a discontinuity
- // Delays makes the offsets smaller than they should be, which is quickly
- // allowed for.
-
- if ((clock_private_info->previous_offset_time != 0) && (jitter > -10000000)) {
-
- if (jitter < 0) {
- if (clock_private_info->follow_up_number < (5 * 8)) // at the beginning (8 samples per second)
- smoothed_offset = clock_private_info->previous_offset + jitter / 16;
- else
- smoothed_offset = clock_private_info->previous_offset + jitter / 64;
- } else if (clock_private_info->follow_up_number <
- (5 * 8)) // at the beginning (8 samples per second)
- smoothed_offset =
- clock_private_info->previous_offset + jitter / 1; // accept positive changes quickly
- else
- smoothed_offset = clock_private_info->previous_offset + jitter / 64;
+void handle_follow_up(char *buf, ssize_t recv_len, clock_source_private_data *clock_private_info,
+ uint64_t reception_time) {
+ if (clock_private_info->clock_id == 0) {
+ debug(2,"Follow_Up received before announcement -- discarded.");
} else {
- // allow samples to disappear for up to a second
- if ((time_since_previous_offset != 0) && (time_since_previous_offset < 1000000000)) {
- smoothed_offset =
- clock_private_info
- ->previous_offset + 1; // if we have recent samples, forget the present sample...
- } else {
- if (clock_private_info->previous_offset_time == 0)
- debug(2, "Clock %" PRIx64 " record (re)starting at %s.", clock_private_info->clock_id,
- clock_private_info->ip);
- else
- debug(2,
- "Timing discontinuity on clock %" PRIx64
- " at %s: time_since_previous_offset: %.3f seconds.",
- clock_private_info->clock_id, clock_private_info->ip,
- 0.000000001 * time_since_previous_offset);
- smoothed_offset = offset;
- clock_private_info->follow_up_number = 0;
- clock_private_info->mastership_start_time =
- reception_time; // mastership is reset to this time...
- }
- }
+ if ((recv_len >= 0) && ((size_t)recv_len >= sizeof(struct ptp_follow_up_message))) {
+ // debug_print_buffer(1, buf, recv_len);
+ struct ptp_follow_up_message *msg = (struct ptp_follow_up_message *)buf;
+ uint16_t seconds_hi = nctohs(&msg->follow_up.preciseOriginTimestamp[0]);
+ uint32_t seconds_low = nctohl(&msg->follow_up.preciseOriginTimestamp[2]);
+ uint32_t nanoseconds = nctohl(&msg->follow_up.preciseOriginTimestamp[6]);
+ uint64_t preciseOriginTimestamp = seconds_hi;
+ preciseOriginTimestamp = preciseOriginTimestamp << 32;
+ preciseOriginTimestamp = preciseOriginTimestamp + seconds_low;
+ preciseOriginTimestamp = preciseOriginTimestamp * 1000000000L;
+ preciseOriginTimestamp = preciseOriginTimestamp + nanoseconds;
+
+ // update our sample information
+
+
+ if (clock_private_info->previous_preciseOriginTimestamp == preciseOriginTimestamp) {
+ clock_private_info->identical_previous_preciseOriginTimestamp_count++;
+
+ if ((clock_private_info->identical_previous_preciseOriginTimestamp_count == 5) && (clock_private_info->follow_up_number < 100)){
+ debug(1,"Clock %" PRIx64 "'s grandmaster clock has stopped or may not have been read.", clock_private_info->clock_id);
+
+
+ debug(1, "Attempt to start a stopped clock %" PRIx64 ", at follow_up_number %u at IP %s.",
+ clock_private_info->clock_id, clock_private_info->follow_up_number,
+ clock_private_info->ip);
+ send_awakening_announcement_sequence(clock_private_info->clock_id, clock_private_info->ip,
+ clock_private_info->family, clock_private_info->grandmasterPriority1,
+ clock_private_info->grandmasterPriority2);
+ }
+ } else {
+ if (clock_private_info->identical_previous_preciseOriginTimestamp_count >= 20) {
+ debug(1,"Clock %" PRIx64 "'s grandmaster clock has started again...", clock_private_info->clock_id);
+ clock_private_info->identical_previous_preciseOriginTimestamp_count = 0;
+ }
+ }
- clock_private_info->previous_offset_grandmaster = clock_private_info->grandmasterIdentity;
- clock_private_info->previous_offset = smoothed_offset;
- clock_private_info->previous_offset_time = reception_time;
-
-/*
- debug(1,
- "Clock %" PRIx64 ", grandmaster %" PRIx64 " at %s. Offset: %" PRIx64 ", smoothed offset: %" PRIx64
- ". Precise Origin Timestamp: %" PRIx64
- ". Time since previous offset: %.3f milliseconds.",
- clock_private_info->clock_id, clock_private_info->grandmasterIdentity, clock_private_info->ip, offset, smoothed_offset,
- preciseOriginTimestamp, 0.000001 * time_since_previous_offset);
-*/
-
- 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(2, "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,
- smoothed_offset, clock_private_info->mastership_start_time);
+
+ clock_private_info->previous_preciseOriginTimestamp = preciseOriginTimestamp;
+
+ // clang-format off
+
+ // actually the precision timestamp needs to be corrected by the Follow_Up Correction_Field contents.
+ // According to IEEE Std 802.1AS-2020, paragraph 11.4.4.2.1:
+ /*
+ The value of the preciseOriginTimestamp field is the sourceTime of the ClockMaster entity of the Grandmaster PTP Instance,
+ when the associated Sync message was sent by that Grandmaster PTP Instance, with any fractional nanoseconds truncated (see 10.2.9).
+ The sum of the correctionFields in the Follow_Up and associated Sync messages, added to the preciseOriginTimestamp field of the Follow_Up message,
+ is the value of the synchronized time corresponding to the syncEventEgressTimestamp at the PTP Instance that sent the associated Sync message,
+ including any fractional nanoseconds.
+ */
+
+ // clang-format on
+
+ int64_t correction_field = ntoh64(msg->header.correctionField);
+
+ // debug(1," Check ntoh64: in: %" PRIx64 ", out: %" PRIx64 ".", msg->header.correctionField, correction_field);
+
+ correction_field = correction_field / 65536; //might be signed
+ uint64_t correctedPreciseOriginTimestamp = preciseOriginTimestamp + correction_field;
+
+
+ if (clock_private_info->follow_up_number < 100)
+ clock_private_info->follow_up_number++;
+
+ // if (clock_private_info->announcements_without_followups < 4) // if we haven't signalled already
+ clock_private_info->announcements_without_followups = 0; // we've seen a followup
+
+ debug(2, "FOLLOWUP from %" PRIx64 ", %s.", clock_private_info->clock_id,
+ &clock_private_info->ip);
+ uint64_t offset = correctedPreciseOriginTimestamp - reception_time;
+
+ int64_t jitter = 0;
+
+ int64_t time_since_previous_offset = 0;
+ uint64_t smoothed_offset = offset;
+
+ // This is a bit hacky.
+ // Basically, the idea is that if the grandmaster has changed, then acceptance checking and
+ // smoothing should start as it it's a new clock. This is because the correctedPreciseOriginTimestamp,
+ // which is part of the data that is being smoothed, refers to the grandmaster, so when the
+ // grandmaster changes any previous calculations are no longer valid. The hacky bit is to signal
+ // this condition by zeroing the previous_offset_time.
+ if (clock_private_info->previous_offset_grandmaster != clock_private_info->grandmasterIdentity)
+ clock_private_info->previous_offset_time =
+ 0;
+
+ if (clock_private_info->previous_offset_time != 0) {
+ time_since_previous_offset = reception_time - clock_private_info->previous_offset_time;
+ }
+
+ // Do acceptance checking and smoothing.
+
+ // Positive changes in the offset are much more likely to be
+ // legitimate, since they could only occur due to a shorter
+ // propagation time or less of a delay sending or receiving the packet.
+ // (Actually, this is not quite true --
+ // it is possible that the remote clock could be adjusted forward
+ // and this would increase the offset too.)
+ // Anyway, when the clock is new, we give extra preferential weighting to
+ // positive changes in the offset.
+
+ // If the new offset is greater, by any amount, than the old offset,
+ // or if it is less by up to 10 mS, accept it.
+ // Otherwise, drop it if the last sample was fairly recent
+ // If the last sample was long ago, take this as a discontinuity and
+ // accept it as the start of a new period of mastership.
+
+ // This seems to be quite stable
+
+ if (clock_private_info->previous_offset_time != 0)
+ jitter = offset - clock_private_info->previous_offset;
+
+ // We take any positive or a limited negative jitter as a sync event in
+ // a continuous synchronisation sequence.
+ // This works well with PTP sources that sleep, as when they sleep
+ // their clock stops. When they awaken, the offset from
+ // the local clock to them must be smaller than before, triggering the
+ // timing discontinuity below and allowing an immediate readjustment.
+
+ // The full value of a positive offset jitter is accepted for a
+ // number of follow_ups at the start.
+ // After that, the weight of the jitter is reduced.
+ // Follow-ups don't always come in at 125 ms intervals, especially after a discontinuity
+ // Delays makes the offsets smaller than they should be, which is quickly
+ // allowed for.
+
+ if ((clock_private_info->previous_offset_time != 0) && (jitter > -10000000)) {
+
+ if (jitter < 0) {
+ if (clock_private_info->follow_up_number <
+ (5 * 8)) // at the beginning (8 samples per second)
+ smoothed_offset = clock_private_info->previous_offset + jitter / 16;
+ else
+ smoothed_offset = clock_private_info->previous_offset + jitter / 64;
+ } else if (clock_private_info->follow_up_number <
+ (5 * 8)) // at the beginning (8 samples per second)
+ smoothed_offset =
+ clock_private_info->previous_offset + jitter / 1; // accept positive changes quickly
+ else
+ smoothed_offset = clock_private_info->previous_offset + jitter / 64;
+ } else {
+ // allow samples to disappear for up to a second
+ if ((time_since_previous_offset != 0) && (time_since_previous_offset < 1000000000) && (jitter > -4000000000L)) {
+ smoothed_offset = clock_private_info->previous_offset +
+ 1; // if we have recent samples, forget the present sample...
+ } else {
+ if (clock_private_info->previous_offset_time == 0)
+ debug(1, "Clock %" PRIx64 " record (re)starting at %s.", clock_private_info->clock_id,
+ clock_private_info->ip);
+ else
+ debug(1,
+ "Timing discontinuity on clock %" PRIx64
+ " at %s: time_since_previous_offset: %.3f seconds.",
+ clock_private_info->clock_id, clock_private_info->ip,
+ 0.000000001 * time_since_previous_offset);
+ smoothed_offset = offset;
+ clock_private_info->follow_up_number = 0;
+ clock_private_info->mastership_start_time =
+ reception_time; // mastership is reset to this time...
+ }
+ }
+
+ clock_private_info->previous_offset_grandmaster = clock_private_info->grandmasterIdentity;
+ clock_private_info->previous_offset = smoothed_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(2,
+ "Clock %" PRIx64 ", grandmaster %" PRIx64 ". Offset: %" PRIx64
+ ", smoothed offset: %" PRIx64 ". Raw Precise Origin Timestamp: %" PRIx64
+ ". Time since previous offset: %8.3f milliseconds. ID: %5u, Follow_Up Number: %u. Source: %s",
+ clock_private_info->clock_id, clock_private_info->grandmasterIdentity, offset,
+ smoothed_offset, preciseOriginTimestamp, 0.000001 * time_since_previous_offset,
+ ntohs(msg->header.sequenceId), clock_private_info->follow_up_number, clock_private_info->ip);
+
+ debug(2, "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,
+ smoothed_offset, clock_private_info->mastership_start_time);
+ }
+ }
+ } else {
+ debug(1, "Follow_Up message is too small to be valid.");
}
}
}
return 0;
}
+void send_awakening_announcement_sequence(const uint64_t clock_id, const char *clock_ip,
+ const int ip_family, const uint8_t priority1,
+ const uint8_t priority2) {
+ struct ptp_announce_message *msg;
+ size_t msg_length = sizeof(struct ptp_announce_message);
+ msg = malloc(msg_length);
+ memset((void *)msg, 0, msg_length);
+
+ 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);
+ if (priority1 > 2) {
+ msg->announce.grandmasterPriority1 =
+ priority1 - 1; // make this announcement seem better than the clock we are about to ping
+ msg->announce.grandmasterPriority2 = priority2;
+ } else {
+ warn("Cannot select a suitable priority for pinging clock %" PRIx64 " at %s.", clock_id,
+ clock_ip);
+ msg->announce.grandmasterPriority1 = 248;
+ msg->announce.grandmasterPriority2 = 248;
+ }
+ msg->announce.timeSource = 160; // Internal Oscillator
+
+ // 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 == ip_family))
+ s = sockets_open_stuff.sockets[t].number;
+ }
+ if (s == 0) {
+ debug(1, "sending socket not found for clock %" PRIx64 " at %s, family %s.", clock_id, clock_ip,
+ ip_family == AF_INET ? "IPv4"
+ : ip_family == AF_INET6 ? "IPv6"
+ : "Unknown");
+ } 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(clock_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
+
+ // debug_print_buffer(1, (char *)msg, msg_length);
+ int ret = sendto(s, msg, msg_length, 0, res->ai_addr, res->ai_addrlen);
+ if (ret == -1)
+ debug(1, "result of sendto is %d.", ret);
+ debug(2, "Send awaken Announce message to clock \"%" PRIx64 "\" at %s on %s.", clock_id, clock_ip,
+ ip_family == AF_INET6 ? "IPv6" : "IPv4");
+
+ if (priority1 < 254) {
+ msg->announce.grandmasterPriority1 =
+ priority1 + 1; // make this announcement seem worse than the clock we about to ping
+ } else {
+ warn("Cannot select a suitable priority for second ping of clock %" PRIx64 " at %s.",
+ clock_id, clock_ip);
+ msg->announce.grandmasterPriority1 = 250;
+ }
+
+ msg->announce.grandmasterPriority2 = priority2;
+ usleep(500000);
+ ret = sendto(s, msg, msg_length, 0, res->ai_addr, res->ai_addrlen);
+ if (ret == -1)
+ debug(1, "result of second sendto is %d.", ret);
+ freeaddrinfo(res);
+ }
+ }
+ free(msg);
+}
+
uint64_t broadcasting_task(uint64_t call_time, __attribute__((unused)) void *private_data) {
clock_source_private_data *clocks_private = (clock_source_private_data *)private_data;
int i;
for (i = 0; i < MAX_CLOCKS; i++) {
if ((clocks_private[i].announcements_without_followups == 3) &&
- (clocks_private[i].follow_up_number == 0) && // only check at the start
+ // (clocks_private[i].follow_up_number == 0) && // only check at the start
((clocks_private[i].flags & (1 << clock_is_one_of_ours)) == 0)) {
- debug(1, "Found a silent clock %" PRIx64 " at %s.", clocks_private[i].clock_id,
+ debug(2, "Attempt to awaken a silent clock %" PRIx64 ", index %u, at follow_up_number %u at IP %s.",
+ clocks_private[i].clock_id, i, clocks_private[i].follow_up_number,
clocks_private[i].ip);
+
// send an Announce message to attempt to waken this silent PTP clock by
// getting it to negotiate with an apparently better clock
// that then immediately sends another Announce message indicating that it's inferior
clocks_private[i].announcements_without_followups++; // set to 4 to indicate done/parked
-
- struct ptp_announce_message *msg;
- size_t msg_length = sizeof(struct ptp_announce_message);
- msg = malloc(msg_length);
- memset((void *)msg, 0, msg_length);
-
- 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);
- if (clocks_private[i].grandmasterPriority1 > 2) {
- msg->announce.grandmasterPriority1 =
- clocks_private[i].grandmasterPriority1 -
- 1; // make this announcement seem better than the clock we are about to ping
- msg->announce.grandmasterPriority2 = clocks_private[i].grandmasterPriority2;
- } else {
- warn("Cannot select a suitable priority for pinging clock %" PRIx64 " at %s.",
- clocks_private[i].clock_id, clocks_private[i].ip);
- msg->announce.grandmasterPriority1 = 248;
- msg->announce.grandmasterPriority2 = 248;
- }
- msg->announce.timeSource = 160; // Internal Oscillator
-
- // 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 clock %" PRIx64 " at %s, family %s.",
- clocks_private[i].clock_id, clocks_private[i].ip,
- clocks_private[i].family == AF_INET ? "IPv4"
- : clocks_private[i].family == AF_INET6 ? "IPv6"
- : "Unknown");
- } 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_print_buffer(1, (char *)msg, msg_length);
- int ret = sendto(s, msg, msg_length, 0, res->ai_addr, res->ai_addrlen);
- if (ret == -1)
- debug(1, "result of sendto is %d.", ret);
- debug(2, "message clock \"%" PRIx64 "\" at %s on %s.", clocks_private[i].clock_id,
- clocks_private[i].ip, clocks_private[i].family == AF_INET6 ? "IPv6" : "IPv4");
-
- if (clocks_private[i].grandmasterPriority1 < 254) {
- msg->announce.grandmasterPriority1 =
- clocks_private[i].grandmasterPriority1 +
- 1; // make this announcement seem worse than the clock we about to ping
- } else {
- warn("Cannot select a suitable priority for second ping of clock %" PRIx64 " at %s.",
- clocks_private[i].clock_id, clocks_private[i].ip);
- msg->announce.grandmasterPriority1 = 250;
- }
-
- msg->announce.grandmasterPriority2 = clocks_private[i].grandmasterPriority2;
- ret = sendto(s, msg, msg_length, 0, res->ai_addr, res->ai_addrlen);
- if (ret == -1)
- debug(1, "result of second sendto is %d.", ret);
- // }
- freeaddrinfo(res);
- }
- }
- free(msg);
+ send_awakening_announcement_sequence(
+ clocks_private[i].clock_id, clocks_private[i].ip, clocks_private[i].family,
+ clocks_private[i].grandmasterPriority1, clocks_private[i].grandmasterPriority2);
}
}