util: add functions for zeroing and comparing NTP timestamps

This commit is contained in:
Miroslav Lichvar 2016-10-24 16:46:29 +02:00
parent 0e273939d2
commit 6e9c04896b
4 changed files with 67 additions and 30 deletions

View file

@ -209,8 +209,8 @@ get_record(IPAddr *ip)
record->ntp_rate = record->cmd_rate = INVALID_RATE;
record->ntp_timeout_rate = INVALID_RATE;
record->flags = 0;
record->ntp_rx_ts.hi = record->ntp_rx_ts.lo = 0;
record->ntp_tx_ts.hi = record->ntp_tx_ts.lo = 0;
UTI_ZeroNtp64(&record->ntp_rx_ts);
UTI_ZeroNtp64(&record->ntp_tx_ts);
return record;
}

View file

@ -599,14 +599,10 @@ NCR_ResetInstance(NCR_Instance instance)
instance->valid_rx = 0;
instance->valid_timestamps = 0;
instance->remote_ntp_rx.hi = 0;
instance->remote_ntp_rx.lo = 0;
instance->remote_ntp_tx.hi = 0;
instance->remote_ntp_tx.lo = 0;
instance->local_ntp_rx.hi = 0;
instance->local_ntp_rx.lo = 0;
instance->local_ntp_tx.hi = 0;
instance->local_ntp_tx.lo = 0;
UTI_ZeroNtp64(&instance->remote_ntp_rx);
UTI_ZeroNtp64(&instance->remote_ntp_tx);
UTI_ZeroNtp64(&instance->local_ntp_rx);
UTI_ZeroNtp64(&instance->local_ntp_tx);
UTI_ZeroTimespec(&instance->local_rx.ts);
instance->local_rx.err = 0.0;
instance->local_rx.source = NTP_TS_DAEMON;
@ -1286,24 +1282,21 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
The test values are 1 when passed and 0 when failed. */
/* Test 1 checks for duplicate packet */
test1 = message->transmit_ts.hi != inst->remote_ntp_tx.hi ||
message->transmit_ts.lo != inst->remote_ntp_tx.lo;
test1 = !!UTI_CompareNtp64(&message->transmit_ts, &inst->remote_ntp_tx);
/* Test 2 checks for bogus packet in the basic and interleaved modes. This
ensures the source is responding to the latest packet we sent to it. */
test2n = message->originate_ts.hi == inst->local_ntp_tx.hi &&
message->originate_ts.lo == inst->local_ntp_tx.lo;
test2n = !UTI_CompareNtp64(&message->originate_ts, &inst->local_ntp_tx);
test2i = inst->interleaved &&
message->originate_ts.hi == inst->local_ntp_rx.hi &&
message->originate_ts.lo == inst->local_ntp_rx.lo;
!UTI_CompareNtp64(&message->originate_ts, &inst->local_ntp_rx);
test2 = test2n || test2i;
interleaved_packet = !test2n && test2i;
/* Test 3 checks for invalid timestamps. This can happen when the
association if not properly 'up'. */
test3 = (message->originate_ts.hi || message->originate_ts.lo) &&
(message->receive_ts.hi || message->receive_ts.lo) &&
(message->transmit_ts.hi || message->transmit_ts.lo);
test3 = !UTI_IsZeroNtp64(&message->originate_ts) &&
!UTI_IsZeroNtp64(&message->receive_ts) &&
!UTI_IsZeroNtp64(&message->transmit_ts);
/* Test 4 would check for denied access. It would always pass as this
function is called only for known sources. */
@ -1817,18 +1810,17 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
on clients that are not using the interleaved mode. */
if (log_index >= 0) {
CLG_GetNtpTimestamps(log_index, &local_ntp_rx, &local_ntp_tx);
interleaved = (local_ntp_rx->hi || local_ntp_rx->lo) &&
message->originate_ts.hi == local_ntp_rx->hi &&
message->originate_ts.lo == local_ntp_rx->lo;
interleaved = !UTI_IsZeroNtp64(local_ntp_rx) &&
!UTI_CompareNtp64(&message->originate_ts, local_ntp_rx);
if (interleaved) {
if (local_ntp_tx->hi || local_ntp_tx->lo)
if (!UTI_IsZeroNtp64(local_ntp_tx))
UTI_Ntp64ToTimespec(local_ntp_tx, &local_tx.ts);
else
interleaved = 0;
tx_ts = &local_tx;
} else {
local_ntp_tx->hi = local_ntp_tx->lo = 0;
UTI_ZeroNtp64(local_ntp_tx);
local_ntp_tx = NULL;
}
}
@ -1857,10 +1849,8 @@ update_tx_timestamp(NTP_Local_Timestamp *tx_ts, NTP_Local_Timestamp *new_tx_ts,
}
/* Check if this is the last packet that was sent */
if ((local_ntp_rx && (message->receive_ts.hi != local_ntp_rx->hi ||
message->receive_ts.lo != local_ntp_rx->lo)) ||
(local_ntp_tx && (message->transmit_ts.hi != local_ntp_tx->hi ||
message->transmit_ts.lo != local_ntp_tx->lo))) {
if ((local_ntp_rx && UTI_CompareNtp64(&message->receive_ts, local_ntp_rx)) ||
(local_ntp_tx && UTI_CompareNtp64(&message->transmit_ts, local_ntp_tx))) {
DEBUG_LOG(LOGF_NtpCore, "RX/TX timestamp mismatch");
return;
}
@ -2236,8 +2226,7 @@ broadcast_timeout(void *arg)
destination = ARR_GetElement(broadcasts, (long)arg);
orig_ts.hi = 0;
orig_ts.lo = 0;
UTI_ZeroNtp64(&orig_ts);
UTI_ZeroTimespec(&recv_ts.ts);
recv_ts.source = NTP_TS_DAEMON;
recv_ts.err = 0.0;

36
util.c
View file

@ -679,6 +679,42 @@ UTI_DoubleToNtp32(double x)
/* ================================================== */
void
UTI_ZeroNtp64(NTP_int64 *ts)
{
ts->hi = ts->lo = htonl(0);
}
/* ================================================== */
int
UTI_IsZeroNtp64(NTP_int64 *ts)
{
return !ts->hi && !ts->lo;
}
/* ================================================== */
int
UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b)
{
int32_t diff;
if (a->hi == b->hi && a->lo == b->lo)
return 0;
diff = ntohl(a->hi) - ntohl(b->hi);
if (diff < 0)
return -1;
if (diff > 0)
return 1;
return ntohl(a->lo) < ntohl(b->lo) ? -1 : 1;
}
/* ================================================== */
/* Seconds part of NTP timestamp correponding to the origin of the time_t format */
#define JAN_1970 0x83aa7e80UL

12
util.h
View file

@ -126,8 +126,20 @@ extern void UTI_GetNtp64Fuzz(NTP_int64 *ts, int precision);
extern double UTI_Ntp32ToDouble(NTP_int32 x);
extern NTP_int32 UTI_DoubleToNtp32(double x);
/* Zero an NTP timestamp */
extern void UTI_ZeroNtp64(NTP_int64 *ts);
/* Check if an NTP timestamp is zero */
extern int UTI_IsZeroNtp64(NTP_int64 *ts);
/* Compare two NTP timestamps. Returns -1 if a is before b, 0 if a is equal to
b, and 1 if a is after b. */
extern int UTI_CompareNtp64(NTP_int64 *a, NTP_int64 *b);
/* Convert a timespec into an NTP timestamp */
extern void UTI_TimespecToNtp64(struct timespec *src, NTP_int64 *dest, NTP_int64 *fuzz);
/* Convert an NTP timestamp into a timespec */
extern void UTI_Ntp64ToTimespec(NTP_int64 *src, struct timespec *dest);
/* Check if time + offset is sane */