sync_seen,
};
-#define MAX_TIMING_SAMPLES 19
+#define MAX_TIMING_SAMPLES 3
typedef struct {
uint64_t local, local_to_remote_offset;
} timing_samples;
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,
// 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);
}
}
// 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;
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) {
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;
+ }
+}
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);
#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>
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;
+}
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
&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: {