From 6372a9f93f59177953f3bf8273aafdeab32648db Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 26 Sep 2023 12:22:47 +0200 Subject: [PATCH] ntp: save PTP correction from NTP-over-PTP messages When the RX duration is known (HW timestamping), save the PTP correction from received PTP messages in the local RX timestamp. --- ntp_io.c | 14 +++++++++++--- ntp_io.h | 2 +- ntp_io_linux.c | 9 +++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/ntp_io.c b/ntp_io.c index f834772..ec2fd7b 100644 --- a/ntp_io.c +++ b/ntp_io.c @@ -459,7 +459,7 @@ process_message(SCK_Message *message, int sock_fd, int event) DEBUG_LOG("Updated RX timestamp delay=%.9f tss=%u", UTI_DiffTimespecsToDouble(&sched_ts, &local_ts.ts), local_ts.source); - if (!NIO_UnwrapMessage(message, sock_fd)) + if (!NIO_UnwrapMessage(message, sock_fd, &local_ts.net_correction)) return; /* Just ignore the packet if it's not of a recognized length */ @@ -498,8 +498,9 @@ read_from_socket(int sock_fd, int event, void *anything) /* ================================================== */ int -NIO_UnwrapMessage(SCK_Message *message, int sock_fd) +NIO_UnwrapMessage(SCK_Message *message, int sock_fd, double *net_correction) { + double ptp_correction; PTP_NtpMessage *msg; if (!is_ptp_socket(sock_fd)) @@ -525,7 +526,14 @@ NIO_UnwrapMessage(SCK_Message *message, int sock_fd) message->data = (char *)message->data + PTP_NTP_PREFIX_LENGTH; message->length -= PTP_NTP_PREFIX_LENGTH; - DEBUG_LOG("Unwrapped PTP->NTP len=%d", message->length); + ptp_correction = UTI_Integer64NetworkToHost(*(Integer64 *)msg->header.correction) / + ((1 << 16) * 1.0e9); + + /* Use the correction only if the RX duration is known (i.e. HW timestamp) */ + if (*net_correction > 0.0) + *net_correction += ptp_correction; + + DEBUG_LOG("Unwrapped PTP->NTP len=%d corr=%.9f", message->length, ptp_correction); return 1; } diff --git a/ntp_io.h b/ntp_io.h index 427bd96..30f4992 100644 --- a/ntp_io.h +++ b/ntp_io.h @@ -64,7 +64,7 @@ extern int NIO_IsServerSocketOpen(void); extern int NIO_IsServerConnectable(NTP_Remote_Address *remote_addr); /* Function to unwrap an NTP message from non-native transport (e.g. PTP) */ -extern int NIO_UnwrapMessage(SCK_Message *message, int sock_fd); +extern int NIO_UnwrapMessage(SCK_Message *message, int sock_fd, double *net_correction); /* Function to transmit a packet */ extern int NIO_SendPacket(NTP_Packet *packet, NTP_Remote_Address *remote_addr, diff --git a/ntp_io_linux.c b/ntp_io_linux.c index 8f93f59..e797f34 100644 --- a/ntp_io_linux.c +++ b/ntp_io_linux.c @@ -559,7 +559,7 @@ process_hw_timestamp(struct Interface *iface, struct timespec *hw_ts, NTP_Local_Timestamp *local_ts, int rx_ntp_length, int family, int l2_length) { - double rx_correction, ts_delay, local_err; + double rx_correction = 0.0, ts_delay, local_err; struct timespec ts; poll_phc(iface, &local_ts->ts); @@ -600,6 +600,10 @@ process_hw_timestamp(struct Interface *iface, struct timespec *hw_ts, local_ts->ts = ts; local_ts->err = local_err; local_ts->source = NTP_TS_HARDWARE; + local_ts->rx_duration = rx_correction; + /* Network correction needs to include the RX duration to avoid + asymmetric correction with asymmetric link speeds */ + local_ts->net_correction = rx_correction; } /* ================================================== */ @@ -723,6 +727,7 @@ NIO_Linux_ProcessMessage(SCK_Message *message, NTP_Local_Address *local_addr, { struct Interface *iface; int is_tx, ts_if_index, l2_length; + double c; is_tx = event == SCH_FILE_EXCEPTION; iface = NULL; @@ -783,7 +788,7 @@ NIO_Linux_ProcessMessage(SCK_Message *message, NTP_Local_Address *local_addr, return 1; } - if (!NIO_UnwrapMessage(message, local_addr->sock_fd)) + if (!NIO_UnwrapMessage(message, local_addr->sock_fd, &c)) return 1; if (message->length < NTP_HEADER_LENGTH || message->length > sizeof (NTP_Packet))