From bf616eafa1549bf45132aeb5c617b769606dfdae Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 21 Sep 2023 14:02:11 +0200 Subject: [PATCH] util: add conversion between intervals and NTP 64-bit format This will be needed to save PTP correction in NTP timestamp format. --- test/unit/util.c | 41 +++++++++++++++++++++++++++++++++++++++++ util.c | 27 +++++++++++++++++++++++++++ util.h | 4 ++++ 3 files changed, 72 insertions(+) diff --git a/test/unit/util.c b/test/unit/util.c index fa294c4..f434671 100644 --- a/test/unit/util.c +++ b/test/unit/util.c @@ -253,6 +253,47 @@ test_unit(void) TEST_CHECK(UTI_IsEqualAnyNtp64(&ntp_ts, NULL, NULL, &ntp_ts)); TEST_CHECK(!UTI_IsEqualAnyNtp64(&ntp_ts, &ntp_fuzz, &ntp_fuzz, &ntp_fuzz)); + ntp_ts.hi = htonl(0); + ntp_ts.lo = htonl(0); + x = UTI_Ntp64ToDouble(&ntp_ts); + TEST_CHECK(fabs(x) < 1e-10); + UTI_DoubleToNtp64(x, &ntp_ts2); + TEST_CHECK(UTI_CompareNtp64(&ntp_ts, &ntp_ts2) == 0); + + ntp_ts.hi = htonl(0); + ntp_ts.lo = htonl(0xffffffff); + x = UTI_Ntp64ToDouble(&ntp_ts); + TEST_CHECK(fabs(x - 1.0 + 0.23e-9) < 1e-10); + UTI_DoubleToNtp64(x, &ntp_ts2); + TEST_CHECK(fabs(UTI_DiffNtp64ToDouble(&ntp_ts, &ntp_ts2)) < 0.3e-9); + + ntp_ts.hi = htonl(0xffffffff); + ntp_ts.lo = htonl(0xffffffff); + x = UTI_Ntp64ToDouble(&ntp_ts); + TEST_CHECK(fabs(x + 0.23e-9) < 1e-10); + UTI_DoubleToNtp64(x, &ntp_ts2); + TEST_CHECK(fabs(UTI_DiffNtp64ToDouble(&ntp_ts, &ntp_ts2)) < 0.3e-9); + + ntp_ts.hi = htonl(0x80000000); + ntp_ts.lo = htonl(0); + x = UTI_Ntp64ToDouble(&ntp_ts); + TEST_CHECK(fabs(x + 0x80000000) < 1e-10); + UTI_DoubleToNtp64(x, &ntp_ts2); + TEST_CHECK(fabs(UTI_DiffNtp64ToDouble(&ntp_ts, &ntp_ts2)) < 0.3e-9); + + ntp_ts.hi = htonl(0x7fffffff); + ntp_ts.lo = htonl(0xffffffff); + x = UTI_Ntp64ToDouble(&ntp_ts); + TEST_CHECK(fabs(x - 2147483648) < 1.0); + + ntp_ts.lo = htonl(0); + ntp_ts.hi = htonl(0x7fffffff); + UTI_DoubleToNtp64(0x7fffffff + 0.1, &ntp_ts2); + TEST_CHECK(UTI_CompareNtp64(&ntp_ts, &ntp_ts2) == 0); + ntp_ts.hi = htonl(0x80000000); + UTI_DoubleToNtp64(0x80000000 - 0.1, &ntp_ts); + TEST_CHECK(UTI_CompareNtp64(&ntp_ts, &ntp_ts2) == 0); + ts.tv_sec = 1; ts.tv_nsec = 2; ts2.tv_sec = 1; diff --git a/util.c b/util.c index a240e3e..a4c8288 100644 --- a/util.c +++ b/util.c @@ -818,6 +818,33 @@ UTI_DiffNtp64ToDouble(const NTP_int64 *a, const NTP_int64 *b) /* ================================================== */ +double +UTI_Ntp64ToDouble(NTP_int64 *src) +{ + NTP_int64 zero; + + UTI_ZeroNtp64(&zero); + return UTI_DiffNtp64ToDouble(src, &zero); +} + +/* ================================================== */ + +void +UTI_DoubleToNtp64(double src, NTP_int64 *dest) +{ + int32_t hi; + + src = CLAMP(INT32_MIN, src, INT32_MAX); + hi = round(src); + if (hi > src) + hi -= 1; + + dest->hi = htonl(hi); + dest->lo = htonl((src - hi) * (1.0e9 * NSEC_PER_NTP64)); +} + +/* ================================================== */ + /* Maximum offset between two sane times */ #define MAX_OFFSET 4294967296.0 diff --git a/util.h b/util.h index d38abf0..9f11ba6 100644 --- a/util.h +++ b/util.h @@ -163,6 +163,10 @@ extern void UTI_Ntp64ToTimespec(const NTP_int64 *src, struct timespec *dest); /* Calculate a - b in any epoch */ extern double UTI_DiffNtp64ToDouble(const NTP_int64 *a, const NTP_int64 *b); +/* Convert a difference in double (not a timestamp) from and to NTP format */ +extern double UTI_Ntp64ToDouble(NTP_int64 *src); +extern void UTI_DoubleToNtp64(double src, NTP_int64 *dest); + /* Check if time + offset is sane */ extern int UTI_IsTimeOffsetSane(const struct timespec *ts, double offset);