From b0267475e33c49db9ca33023468b96c55cfacc68 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 26 Sep 2023 12:14:56 +0200 Subject: [PATCH] ntp: extend local timestamp for PTP correction Add two new fields to the NTP_Local_Timestamp structure: - receive duration as the time it takes to receive the ethernet frame, currently known only with HW timestamping - network correction as a generalized PTP correction The PTP correction is provided by transparent clocks in the correction field of PTP messages to remove the receive, processing and queueing delays of network switches and routers. Only one-step end-to-end unicast transparent clocks are useful for NTP-over-PTP. Two-step transparent clocks use follow-up messages and peer-to-peer transparent clocks don't handle delay requests. The RX duration will be included in the network correction to compensate for asymmetric link speeds of the server and client as the NTP RX timestamp corresponds to the end of the reception (in order to compensate for the asymmetry in the normal case when no corrections are applied). --- ntp_core.c | 7 +++++-- ntp_core.h | 2 ++ ntp_io.c | 3 +++ test/unit/ntp_core.c | 6 +++--- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ntp_core.c b/ntp_core.c index 0e41573..fae5e7b 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -420,6 +420,8 @@ zero_local_timestamp(NTP_Local_Timestamp *ts) UTI_ZeroTimespec(&ts->ts); ts->err = 0.0; ts->source = NTP_TS_DAEMON; + ts->rx_duration = 0.0; + ts->net_correction = 0.0; } /* ================================================== */ @@ -1299,6 +1301,8 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ local_tx->ts = local_transmit; local_tx->err = local_transmit_err; local_tx->source = NTP_TS_DAEMON; + local_tx->rx_duration = 0.0; + local_tx->net_correction = 0.0; } if (local_ntp_rx) @@ -2612,8 +2616,7 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a UTI_CompareNtp64(&message->receive_ts, &message->transmit_ts) != 0) { ntp_rx = message->originate_ts; local_ntp_rx = &ntp_rx; - UTI_ZeroTimespec(&local_tx.ts); - local_tx.source = NTP_TS_DAEMON; + zero_local_timestamp(&local_tx); interleaved = CLG_GetNtpTxTimestamp(&ntp_rx, &local_tx.ts, &local_tx.source); tx_ts = &local_tx; diff --git a/ntp_core.h b/ntp_core.h index a3c5546..5c5a614 100644 --- a/ntp_core.h +++ b/ntp_core.h @@ -42,6 +42,8 @@ typedef struct { struct timespec ts; double err; NTP_Timestamp_Source source; + double rx_duration; + double net_correction; } NTP_Local_Timestamp; /* This is a private data type used for storing the instance record for diff --git a/ntp_io.c b/ntp_io.c index fce7b17..f834772 100644 --- a/ntp_io.c +++ b/ntp_io.c @@ -431,6 +431,9 @@ process_message(SCK_Message *message, int sock_fd, int event) SCH_GetLastEventTime(&local_ts.ts, &local_ts.err, NULL); local_ts.source = NTP_TS_DAEMON; + local_ts.rx_duration = 0.0; + local_ts.net_correction = 0.0; + sched_ts = local_ts.ts; if (message->addr_type != SCK_ADDR_IP) { diff --git a/test/unit/ntp_core.c b/test/unit/ntp_core.c index 08a1532..989b294 100644 --- a/test/unit/ntp_core.c +++ b/test/unit/ntp_core.c @@ -99,8 +99,8 @@ send_request(NCR_Instance inst, int late_hwts) local_addr.ip_addr.family = IPADDR_UNSPEC; local_addr.if_index = INVALID_IF_INDEX; local_addr.sock_fd = 101; + zero_local_timestamp(&local_ts); local_ts.ts = current_time; - local_ts.err = 0.0; local_ts.source = NTP_TS_KERNEL; NCR_ProcessTxKnown(inst, &local_addr, &local_ts, &req_buffer, req_length); @@ -122,8 +122,8 @@ process_request(NTP_Remote_Address *remote_addr) local_addr.ip_addr.family = IPADDR_UNSPEC; local_addr.if_index = INVALID_IF_INDEX; local_addr.sock_fd = 100; + zero_local_timestamp(&local_ts); local_ts.ts = current_time; - local_ts.err = 0.0; local_ts.source = NTP_TS_KERNEL; res_length = 0; @@ -289,8 +289,8 @@ proc_response(NCR_Instance inst, int good, int valid, int updated_sync, local_addr.ip_addr.family = IPADDR_UNSPEC; local_addr.if_index = INVALID_IF_INDEX; local_addr.sock_fd = NTP_LVM_TO_MODE(res->lvm) != MODE_SERVER ? 100 : 101; + zero_local_timestamp(&local_ts); local_ts.ts = current_time; - local_ts.err = 0.0; local_ts.source = NTP_TS_KERNEL; prev_rx_count = inst->report.total_rx_count;