Copy root delay/dispersion errors from upstream server (after first upstream NTP synchronization)

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER
2024-06-10 17:12:09 +02:00
parent a05bf8dd24
commit 27db8a43ce
3 changed files with 54 additions and 22 deletions
+36 -10
View File
@@ -122,24 +122,29 @@ void print_debug_time(const char *label, const uint32_t *u32p, const uint64_t nt
(timevar >> 32) & 0xFFFFFFFF, timevar & 0xFFFFFFFF, time_str);
}
static bool settime_step(const double offset)
static uint64_t get_new_time(struct timeval *unix_time, const double offset)
{
// Get current time
struct timeval unix_time;
gettimeofday(&unix_time, NULL);
gettimeofday(unix_time, NULL);
// Convert from double to native format (signed) and add to the
// current time. Note the addition is done in native format to
// avoid overflow or loss of precision.
const uint64_t ntp_time = U2LFP(unix_time) + D2LFP(offset);
const uint64_t ntp_time = U2LFP(*unix_time) + D2LFP(offset);
// Convert NTP to native format
unix_time.tv_sec = NTPtoSEC(ntp_time);
unix_time.tv_usec = NTPtoUSEC(ntp_time);
unix_time->tv_sec = NTPtoSEC(ntp_time);
unix_time->tv_usec = NTPtoUSEC(ntp_time);
return ntp_time;
}
static bool settime_step(struct timeval *unix_time, const double offset)
{
log_debug(DEBUG_NTP, "Stepping system time by %e s", offset);
// Set time immediately
if(settimeofday(&unix_time, NULL) != 0)
if(settimeofday(unix_time, NULL) != 0)
{
log_err("Failed to set time: %s",
errno == EPERM ? "Insufficient permissions, try running with sudo" : strerror(errno));
@@ -221,9 +226,16 @@ static bool reply(int fd, struct ntp_sync *ntp, const bool verbose)
// Compute precision of server clock in seconds 2^rho
ntp->precision = pow(2, rho);
// Get root delay and dispersion (in network-byte-order !)
memcpy(&ntp_root_delay, &buf[4], sizeof(ntp_root_delay));
memcpy(&ntp_root_dispersion, &buf[8], sizeof(ntp_root_dispersion));
// Extract Transmit Timestamp
// org = Origin Timestamp (Transmit Timestamp @ Client)
uint64_t netbuffer;
// ref = Reference Timestamp (Time at which the clock was last set or corrected)
memcpy(&netbuffer, &buf[16], sizeof(netbuffer));
const uint64_t ref = ntoh64(netbuffer);
// org = Origin Timestamp (Transmit Timestamp @ Client)
memcpy(&netbuffer, &buf[24], sizeof(netbuffer));
const uint64_t org = ntoh64(netbuffer);
// rec = Receive Timestamp (Receive Timestamp @ Server)
@@ -287,6 +299,9 @@ static bool reply(int fd, struct ntp_sync *ntp, const bool verbose)
if(!config.debug.ntp.v.b)
return true;
// Print current time at server
print_debug_time("Server reference time", NULL, ref);
// Print current time at client
print_debug_time("Current time at client", NULL, dst);
@@ -296,6 +311,10 @@ static bool reply(int fd, struct ntp_sync *ntp, const bool verbose)
// Print offset and delay
log_debug(DEBUG_NTP, "Time offset: %e s", ntp->theta);
log_debug(DEBUG_NTP, "Round-trip delay: %e s", ntp->delta);
const uint32_t root_delay = ntohl(ntp_root_delay);
log_debug(DEBUG_NTP, "Root delay: %e s", LFP2D(root_delay));
const uint32_t root_dispersion = ntohl(ntp_root_dispersion);
log_debug(DEBUG_NTP, "Root dispersion: %e s", LFP2D(root_dispersion));
return true;
}
@@ -398,7 +417,7 @@ bool ntp_client(const char *server, const bool settime, const bool print)
free(ntp);
return false;
}
log_info("Received %u/%u valid NTP replies", valid, count);
log_info("Received %u/%u valid NTP replies from %s", valid, count, server);
theta_avg /= valid;
delta_avg /= valid;
@@ -466,6 +485,10 @@ bool ntp_client(const char *server, const bool settime, const bool print)
// Set time if requested
if(settime)
{
// Calculate corrected time
struct timeval unix_time;
const uint64_t ntp_time = get_new_time(&unix_time, theta_trim);
// If the clock deviates more than 0.5 seconds from the NTP server,
// the time is updated immediately. Otherwise, the time is updated
// gradually to avoid sudden jumps in the system clock.
@@ -473,7 +496,7 @@ bool ntp_client(const char *server, const bool settime, const bool print)
// since Linux 2.6.26, see man ntp_adjtime(2) for details.
bool success;
if(fabs(theta_trim) > 0.5)
success = settime_step(theta_trim);
success = settime_step(&unix_time, theta_trim);
else
success = settime_skew(theta_trim);
@@ -481,6 +504,9 @@ bool ntp_client(const char *server, const bool settime, const bool print)
if(!success)
return false;
// Update last NTP sync time
ntp_last_sync = ntp_time;
// Finally, adjust RTC if configured
if(config.ntp.rtc.set.v.b)
ntp_sync_rtc();
+4
View File
@@ -65,6 +65,10 @@ bool ntp_sync_rtc(void);
#define hton64(x) ((((uint64_t)htonl(x)) << 32) + htonl((x) >> 32))
#define ntoh64(x) ((((uint64_t)ntohl(x)) << 32) + ntohl((x) >> 32))
extern uint64_t ntp_last_sync;
extern uint32_t ntp_root_delay;
extern uint32_t ntp_root_dispersion;
#endif // NTP_H
+14 -12
View File
@@ -38,6 +38,10 @@
// PRIi64
#include <inttypes.h>
uint64_t ntp_last_sync = 0u;
uint32_t ntp_root_delay = 0u;
uint32_t ntp_root_dispersion = 0u;
// RFC 5905 Appendix A.4: Kernel System Clock Interface
uint64_t gettime64(void)
{
@@ -100,11 +104,12 @@ static bool ntp_reply(const int socket_fd, const struct sockaddr *saddr_p, const
// | Root Dispersion |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// Assume Root Delay (total roundtrip delay to the primary reference
// source) = 0, Root Dispersion (the nominal error relative to the
// primary reference source) = 0 as we don't have these numbers
*u32p++ = 0.0;
*u32p++ = 0.0;
// Set Root Delay (total roundtrip delay to the primary reference
// source) and Root Dispersion (the nominal error relative to the
// primary reference source) to the values obtained from the upstream
// NTP server. These values are already in network byte order.
*u32p++ = ntp_root_delay;
*u32p++ = ntp_root_dispersion;
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -115,7 +120,7 @@ static bool ntp_reply(const int socket_fd, const struct sockaddr *saddr_p, const
// Reference ID = 'LOCL" (LOCAL CLOCK)
// A four-octet, left-justified, zero-padded ASCII string assigned to
// the reference clock
memcpy(u32p++, "LOCL", 4);
memcpy(u32p++, "LOCL", sizeof(uint32_t));
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -126,12 +131,9 @@ static bool ntp_reply(const int socket_fd, const struct sockaddr *saddr_p, const
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// Time when the system clock was last set or corrected, in NTP
// timestamp format. As this is not a stratum 1 server, we don't have
// a hardware clock to set this value.
// A stateless server copies T3 and T4 from the client packet to T1 and
// T2 of the server packet and tacks on the transmit timestamp T3 before
// sending it to the client.
memcpy(u32p, &u32r[8], sizeof(uint64_t));
// timestamp format.
const uint64_t last_sync = hton64(ntp_last_sync);
memcpy(u32p, &last_sync, sizeof(uint64_t));
if(config.debug.ntp.v.b)
print_debug_time("Reference Timestamp", u32p, 0);
u32p += 2;