freeifaddrs(ifap);
}
+void debug_log_nqptp_status(int level) {
+ int records_in_use = 0;
+ int i;
+ for (i = 0; i < MAX_CLOCKS; i++)
+ if (clocks_private[i].in_use != 0)
+ records_in_use++;
+ 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);
+ uint32_t peer_master_mask = peer_clock_mask | (1 << clock_is_master);
+ uint32_t peer_becoming_master_mask = peer_clock_mask | (1 << clock_is_becoming_master);
+ uint32_t non_peer_clock_mask = (1 << clock_is_valid);
+ uint32_t non_peer_master_mask = non_peer_clock_mask | (1 << clock_is_master);
+ for (i = 0; i < MAX_CLOCKS; i++) {
+ if (clocks_private[i].in_use != 0) {
+ if ((clocks_private[i].flags & peer_master_mask) == peer_master_mask) {
+ debug(level, " Peer Master: %" PRIx64 " %s.", clocks_private[i].clock_id,
+ clocks_private[i].ip);
+ } else if ((clocks_private[i].flags & peer_becoming_master_mask) == peer_becoming_master_mask) {
+ debug(level, " Peer Becoming Master: %" PRIx64 " %s.", clocks_private[i].clock_id,
+ clocks_private[i].ip);
+ } else if ((clocks_private[i].flags & peer_clock_mask) == peer_clock_mask) {
+ debug(level, " Peer Clock: %" PRIx64 " %s.", clocks_private[i].clock_id,
+ clocks_private[i].ip);
+ } else if ((clocks_private[i].flags & peer_mask) == peer_mask) {
+ debug(level, " Peer: %s.", clocks_private[i].ip);
+ } else if ((clocks_private[i].flags & non_peer_master_mask) == non_peer_master_mask) {
+ debug(level, " Non Peer Master: %" PRIx64 " %s.", clocks_private[i].clock_id,
+ clocks_private[i].ip);
+ } else if ((clocks_private[i].flags & non_peer_clock_mask) == non_peer_clock_mask) {
+ debug(level, " Non Peer Clock: %16" PRIx64 " %s.", clocks_private[i].clock_id,
+ clocks_private[i].ip);
+ } else {
+ debug(level, " Non Peer Record: %s.", clocks_private[i].ip);
+ }
+ }
+ }
+ }
+}
+
void update_master() {
// note -- this is definitely incomplete -- it doesn't do the full
// data set comparison specified by the IEEE 588 standard
if (old_master == -1)
old_master = i; // find old master
clocks_private[i].flags &= ~(1 << clock_is_master); // turn them all off
+ clocks_private[i].flags &= ~(1 << clock_is_becoming_master); // turn them all off
}
int best_so_far = -1;
debug(1, "No master clock not found!");
} else {
// we found a master clock
- clocks_private[best_so_far].flags |= (1 << clock_is_master);
-
- if (old_master != best_so_far) {
- uint64_t oldest_acceptable_master_clock_time =
- clocks_private[best_so_far].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 = clocks_private[best_so_far].local_to_source_time_offset;
- uint64_t age_of_oldest_legitimate_sample = clocks_private[best_so_far].local_time;
-
- int number_of_samples = MAX_TIMING_SAMPLES - clocks_private[best_so_far].vacant_samples;
- int samples_checked = 0;
- if (number_of_samples > 0) {
- debug(3, "Number of samples: %d.", number_of_samples);
- uint64_t time_now = get_time_now();
-
- // 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 = time_now - 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 = time_now - clocks_private[best_so_far].samples[i].local_time;
-
- int64_t age_relative_to_oldest_acceptable_time =
- clocks_private[best_so_far].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 (clocks_private[best_so_far].samples[i].local_time <
- age_of_oldest_legitimate_sample) {
- age_of_oldest_legitimate_sample = clocks_private[best_so_far].samples[i].local_time;
- }
- uint64_t possible_offset = clocks_private[best_so_far].samples[i].clock_time -
- clocks_private[best_so_far].samples[i].local_time;
- uint64_t possible_master_clock_time =
- clocks_private[best_so_far].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");
- }
- } else {
- debug(3, "sample too old at %f seconds old.", 0.000000001 * age);
- }
- }
- }
-
- // it is possible that the clock has been designated master without any valid recent samples
- // in which case the number of valid samples will be zero.
- if (samples_checked == 0) {
- debug(2,"clock %" PRIx64 " has become master without any recent samples...", clocks_private[best_so_far].clock_id);
- // having no samples is a flag for the first FOLLOW_UP to set the bus mastership start time
- // to its own reception time.
- clocks_private[best_so_far].vacant_samples = MAX_TIMING_SAMPLES; // discard all samples
- } else {
- clocks_private[best_so_far].mastership_start_time = age_of_oldest_legitimate_sample;
- int64_t offset_difference =
- best_offset_so_far - clocks_private[best_so_far].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);
- clocks_private[best_so_far].local_to_source_time_offset = best_offset_so_far;
-
- debug(2, "Master sampling started %f ms before becoming master.",
- 0.000001 * (clocks_private[best_so_far].local_time - age_of_oldest_legitimate_sample));
- update_master_clock_info(clocks_private[best_so_far].clock_id,
- (const char *)&clocks_private[best_so_far].ip,
- clocks_private[best_so_far].local_time,
- clocks_private[best_so_far].local_to_source_time_offset,
- clocks_private[best_so_far].mastership_start_time);
- }
+ if (old_master != best_so_far) {
+ // if the naster is a new one
clocks_private[best_so_far].previous_offset_time = 0; // resync
+ clocks_private[best_so_far].flags |= (1 << clock_is_becoming_master);
+ } else {
+ // if its the same one as before
+ clocks_private[best_so_far].flags |= (1 << clock_is_master);
}
}
-
- int records_in_use = 0;
- for (i = 0; i < MAX_CLOCKS; i++)
- if (clocks_private[i].in_use != 0)
- records_in_use++;
- if (records_in_use > 0) {
- debug(1, "");
- debug(1, "Current NQPTP Status:");
- uint32_t peer_mask = (1 << clock_is_a_timing_peer);
- uint32_t peer_clock_mask = peer_mask | (1 << clock_is_valid);
- uint32_t peer_master_mask = peer_clock_mask | (1 << clock_is_master);
- uint32_t non_peer_clock_mask = (1 << clock_is_valid);
- uint32_t non_peer_master_mask = non_peer_clock_mask | (1 << clock_is_master);
- for (i = 0; i < MAX_CLOCKS; i++) {
- if (clocks_private[i].in_use != 0) {
- if ((clocks_private[i].flags & peer_master_mask) == peer_master_mask) {
- debug(1, " Peer Master: %" PRIx64 " %s.", clocks_private[i].clock_id,
- clocks_private[i].ip);
- } else if ((clocks_private[i].flags & peer_clock_mask) == peer_clock_mask) {
- debug(1, " Peer Clock: %" PRIx64 " %s.", clocks_private[i].clock_id,
- clocks_private[i].ip);
- } else if ((clocks_private[i].flags & peer_mask) == peer_mask) {
- debug(1, " Peer: %s.", clocks_private[i].ip);
- } else if ((clocks_private[i].flags & non_peer_master_mask) == non_peer_master_mask) {
- debug(1, " Non Peer Master: %" PRIx64 " %s.", clocks_private[i].clock_id,
- clocks_private[i].ip);
- } else if ((clocks_private[i].flags & non_peer_clock_mask) == non_peer_clock_mask) {
- debug(1, " Non Peer Clock: %" PRIx64 " %s.", clocks_private[i].clock_id,
- clocks_private[i].ip);
- } else {
- debug(1, " Non Peer Record: %s.", clocks_private[i].ip);
- }
- }
- }
- }
+ debug_log_nqptp_status(1);
}
clock_private_info->next_sample_goes_here = 0;
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;
- // if there has never been a previous follow_up or if it was long ago (more than 15 seconds),
- // don't use it
- if (clock_private_info->previous_offset_time != 0) {
+
+ 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.
+ 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");
+ }
+ } 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));
+ clock_private_info->flags &= ~(1 << clock_is_becoming_master);
+ clock_private_info->flags |= 1 << clock_is_master;
+ } 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;
int64_t sync_timeout = 60000000000; // nanoseconds
debug(2, "Sync interval: %f seconds.", 0.000000001 * time_since_last_sync);
clock_private_info->last_sync_time = reception_time;
}
- uint32_t old_flags = clock_private_info->flags;
-
clock_private_info->local_time = reception_time;
clock_private_info->source_time = preciseOriginTimestamp;
clock_private_info->local_to_source_time_offset = offset;
- if (old_flags != clock_private_info->flags) {
- update_master();
- } else if ((clock_private_info->flags & (1 << clock_is_master)) != 0) {
- // if there were no prior samples, then this must be the first sample with this clock
- // as master. Therefore set its mastership_start_time to the reception time.
- if (clock_private_info->vacant_samples == (MAX_TIMING_SAMPLES - 1)) {
- debug(2,"Clock %" PRIx64 " became a bus master with no valid prior samples -- this is its first one.", clock_private_info->clock_id);
- clock_private_info->mastership_start_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);
debug(3, "clock: %" PRIx64 ", time: %" PRIu64 ", offset: %" PRId64 ", jitter: %+f ms.",