From: Miroslav Lichvar Date: Tue, 1 Aug 2017 15:29:47 +0000 (+0200) Subject: ntp: limit number of interleaved responses in symmetric mode X-Git-Tag: 3.2-pre2~40 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=64c2fd9888d02f5427a5df02a4b6c4a2abc3476b;p=thirdparty%2Fchrony.git ntp: limit number of interleaved responses in symmetric mode In symmetric mode, don't send a packet in interleaved mode unless it is the first response to the last valid request received from the peer and there was just one response to the previous valid request. This prevents the peer from matching the transmit timestamp with an older response if it can't detect missed responses. --- diff --git a/ntp_core.c b/ntp_core.c index e18e7fd4..3442d14b 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -181,6 +181,7 @@ struct NCR_Instance_Record { /* Previous values of some variables needed in interleaved mode */ NTP_Local_Timestamp prev_local_tx; int prev_local_poll; + unsigned int prev_tx_count; /* The instance record in the main source management module. This performs the statistical analysis on the samples we generate */ @@ -655,8 +656,10 @@ NCR_ResetInstance(NCR_Instance instance) UTI_ZeroNtp64(&instance->local_ntp_rx); UTI_ZeroNtp64(&instance->local_ntp_tx); zero_local_timestamp(&instance->local_rx); + zero_local_timestamp(&instance->prev_local_tx); instance->prev_local_poll = 0; + instance->prev_tx_count = 0; } /* ================================================== */ @@ -1072,7 +1075,7 @@ transmit_timeout(void *arg) { NCR_Instance inst = (NCR_Instance) arg; NTP_Local_Address local_addr; - int sent; + int interleaved, sent; inst->tx_timeout_id = 0; @@ -1112,18 +1115,27 @@ transmit_timeout(void *arg) local_addr.if_index = INVALID_IF_INDEX; local_addr.sock_fd = inst->local_addr.sock_fd; + /* In symmetric mode, don't send a packet in interleaved mode unless it + is the first response to the last valid request received from the peer + and there was just one response to the previous valid request. This + prevents the peer from matching the transmit timestamp with an older + response if it can't detect missed responses. */ + interleaved = inst->interleaved && + (inst->mode == MODE_CLIENT || + (inst->prev_tx_count == 1 && inst->tx_count == 0)); + /* Check whether we need to 'warm up' the link to the other end by sending an NTP exchange to ensure both ends' ARP caches are primed or whether we need to send two packets first to ensure a server in the interleaved mode has a fresh timestamp for us. */ if (inst->presend_minpoll <= inst->local_poll && !inst->presend_done && !inst->burst_total_samples_to_go) { - inst->presend_done = inst->interleaved ? 2 : 1; + inst->presend_done = interleaved ? 2 : 1; } else if (inst->presend_done > 0) { inst->presend_done--; } - sent = transmit_packet(inst->mode, inst->interleaved, inst->local_poll, + sent = transmit_packet(inst->mode, interleaved, inst->local_poll, inst->version, inst->auth_mode, inst->auth_key_id, &inst->remote_ntp_rx, &inst->remote_ntp_tx, @@ -1624,6 +1636,7 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr, message->stratum : NTP_MAX_STRATUM; inst->prev_local_poll = inst->local_poll; + inst->prev_tx_count = inst->tx_count; inst->tx_count = 0; SRC_UpdateReachability(inst->source, synced_packet); diff --git a/test/simulation/122-xleave b/test/simulation/122-xleave index e0ce9eca..93f767e9 100755 --- a/test/simulation/122-xleave +++ b/test/simulation/122-xleave @@ -17,6 +17,7 @@ max_sync_time=500 base_delay="(+ 1e-4 (* -1 (equal 0.1 from 2) (equal 0.1 to 1)))" client_lpeer_options="xleave minpoll 5 maxpoll 5" +client_rpeer_options="minpoll 5 maxpoll 5" run_test || test_fail check_chronyd_exit || test_fail