ntpd: show real, unclamped delays on low-latency networks
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 3 Aug 2018 09:03:55 +0000 (11:03 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 3 Aug 2018 09:14:22 +0000 (11:14 +0200)
On fast network, I've seen "delay:0.002000" shown for all packets,
thus completely losing information on what real delays are.

The new code is careful to not reject packets with tiny delays
if the delay "grows a lot" but is still tiny:
0.000009 is "much larger" than 0.000001 (nine times larger),
but is still very good small delay.

function                                             old     new   delta
recv_and_process_peer_pkt                            863     889     +26

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/ntpd.c

index 7462113ce070099db7b60cfd3771eb1b325fbf79..991c518f6aa9fb8d4e7879db30ffed1a6d35a3ca 100644 (file)
 
 #define INITIAL_SAMPLES    4    /* how many samples do we want for init */
 #define MIN_FREQHOLD      12    /* adjust offset, but not freq in this many first adjustments */
-#define BAD_DELAY_GROWTH   4    /* drop packet if its delay grew by more than this */
+#define BAD_DELAY_GROWTH   4    /* drop packet if its delay grew by more than this factor */
 
 #define RETRY_INTERVAL    32    /* on send/recv error, retry in N secs (need to be power of 2) */
 #define NOREPLY_INTERVAL 512    /* sent, but got no reply: cap next query by this many seconds */
@@ -1819,7 +1819,7 @@ update_local_clock(peer_t *p)
        VERB2 bb_error_msg("update from:%s offset:%+f delay:%f jitter:%f clock drift:%+.3fppm tc:%d",
                        p->p_dotted,
                        offset,
-                       p->lastpkt_delay,
+                       p->p_raw_delay,
                        G.discipline_jitter,
                        (double)tmx.freq / 65536,
                        (int)tmx.constant
@@ -1976,27 +1976,30 @@ recv_and_process_peer_pkt(peer_t *p)
        T2 = lfp_to_d(msg.m_rectime);
        T3 = lfp_to_d(msg.m_xmttime);
        T4 = G.cur_time;
-
-       /* The delay calculation is a special case. In cases where the
-        * server and client clocks are running at different rates and
-        * with very fast networks, the delay can appear negative. In
-        * order to avoid violating the Principle of Least Astonishment,
-        * the delay is clamped not less than the system precision.
-        */
        delay = (T4 - T1) - (T3 - T2);
-       if (delay < G_precision_sec)
-               delay = G_precision_sec;
+
        /*
         * If this packet's delay is much bigger than the last one,
         * it's better to just ignore it than use its much less precise value.
         */
        prev_delay = p->p_raw_delay;
-       p->p_raw_delay = delay;
-       if (p->reachable_bits && delay > prev_delay * BAD_DELAY_GROWTH) {
+       p->p_raw_delay = (delay < 0 ? 0.0 : delay);
+       if (p->reachable_bits
+        && delay > prev_delay * BAD_DELAY_GROWTH
+        && delay > 1.0 / (8 * 1024) /* larger than ~0.000122 */
+       ) {
                bb_error_msg("reply from %s: delay %f is too high, ignoring", p->p_dotted, delay);
                goto pick_normal_interval;
        }
 
+       /* The delay calculation is a special case. In cases where the
+        * server and client clocks are running at different rates and
+        * with very fast networks, the delay can appear negative. In
+        * order to avoid violating the Principle of Least Astonishment,
+        * the delay is clamped not less than the system precision.
+        */
+       if (delay < G_precision_sec)
+               delay = G_precision_sec;
        p->lastpkt_delay = delay;
        p->lastpkt_recv_time = T4;
        VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
@@ -2024,7 +2027,7 @@ recv_and_process_peer_pkt(peer_t *p)
                bb_error_msg("reply from %s: offset:%+f delay:%f status:0x%02x strat:%d refid:0x%08x rootdelay:%f reach:0x%02x",
                        p->p_dotted,
                        offset,
-                       p->lastpkt_delay,
+                       p->p_raw_delay,
                        p->lastpkt_status,
                        p->lastpkt_stratum,
                        p->lastpkt_refid,