ntpd: truly ignore high delay packet
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 19 Apr 2014 17:00:16 +0000 (19:00 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 19 Apr 2014 17:00:16 +0000 (19:00 +0200)
Before this cahnge, sometimes they were used after the next packet
from another peer was received, because we did updare some peer stats
from high delay packet before dropping it.

function                                             old     new   delta
recv_and_process_peer_pkt                            922     966     +44

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

index adda6e5b0e0eb70bcfa6a891d4815d513837373e..2eec99f99f0fc1a48c6e5700e143bfd405692239 100644 (file)
@@ -252,6 +252,9 @@ typedef struct {
         * or when receive times out (if p_fd >= 0): */
        double           next_action_time;
        double           p_xmttime;
+       double           p_raw_delay;
+       /* p_raw_delay is set even by "high delay" packets */
+       /* lastpkt_delay isn't */
        double           lastpkt_recv_time;
        double           lastpkt_delay;
        double           lastpkt_rootdelay;
@@ -1685,7 +1688,8 @@ recv_and_process_peer_pkt(peer_t *p)
        ssize_t     size;
        msg_t       msg;
        double      T1, T2, T3, T4;
-       double      dv, offset;
+       double      offset;
+       double      prev_delay, delay;
        unsigned    interval;
        datapoint_t *datapoint;
        peer_t      *q;
@@ -1745,12 +1749,6 @@ recv_and_process_peer_pkt(peer_t *p)
 //     if (msg.m_rootdelay / 2 + msg.m_rootdisp >= MAXDISP || p->lastpkt_reftime > msg.m_xmt)
 //             return;                 /* invalid header values */
 
-       p->lastpkt_status = msg.m_status;
-       p->lastpkt_stratum = msg.m_stratum;
-       p->lastpkt_rootdelay = sfp_to_d(msg.m_rootdelay);
-       p->lastpkt_rootdisp = sfp_to_d(msg.m_rootdisp);
-       p->lastpkt_refid = msg.m_refid;
-
        /*
         * From RFC 2030 (with a correction to the delay math):
         *
@@ -1770,28 +1768,35 @@ recv_and_process_peer_pkt(peer_t *p)
        T3 = lfp_to_d(msg.m_xmttime);
        T4 = G.cur_time;
 
-       p->lastpkt_recv_time = T4;
-       VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_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.
         */
-       dv = p->lastpkt_delay;
-       p->lastpkt_delay = (T4 - T1) - (T3 - T2);
-       if (p->lastpkt_delay < G_precision_sec)
-               p->lastpkt_delay = G_precision_sec;
+       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.
         */
-       if (p->reachable_bits && p->lastpkt_delay > dv * BAD_DELAY_GROWTH) {
+       prev_delay = p->p_raw_delay;
+       p->p_raw_delay = delay;
+       if (p->reachable_bits && delay > prev_delay * BAD_DELAY_GROWTH) {
                bb_error_msg("reply from %s: delay %f is too high, ignoring", p->p_dotted, p->lastpkt_delay);
                goto pick_normal_interval;
        }
 
+       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);
+       p->lastpkt_status = msg.m_status;
+       p->lastpkt_stratum = msg.m_stratum;
+       p->lastpkt_rootdelay = sfp_to_d(msg.m_rootdelay);
+       p->lastpkt_rootdisp = sfp_to_d(msg.m_rootdisp);
+       p->lastpkt_refid = msg.m_refid;
+
        p->datapoint_idx = p->reachable_bits ? (p->datapoint_idx + 1) % NUM_DATAPOINTS : 0;
        datapoint = &p->filter_datapoint[p->datapoint_idx];
        datapoint->d_recv_time = T4;