summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko2010-01-02 15:57:07 +0100
committerDenys Vlasenko2010-01-02 15:57:07 +0100
commit1ee5afdce28d5a11987071f710c1d2fd493618cc (patch)
treef6de1959d1c5ffc8b74c5a3f1940498602140be6
parentf25252c69e4b46917daa799d2ebe4b4f4da9410d (diff)
downloadbusybox-1ee5afdce28d5a11987071f710c1d2fd493618cc.zip
busybox-1ee5afdce28d5a11987071f710c1d2fd493618cc.tar.gz
ntpd: fix jitter calculations and status propagation
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/ntpd.c119
1 files changed, 58 insertions, 61 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
index cabfb79..92e2723 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -166,7 +166,7 @@ typedef struct {
int p_fd;
int datapoint_idx;
uint32_t lastpkt_refid;
- uint8_t lastpkt_leap;
+ uint8_t lastpkt_status;
uint8_t lastpkt_stratum;
uint8_t p_reachable_bits;
double p_xmttime;
@@ -216,7 +216,7 @@ struct globals {
* in stratum 2+ packets, it's IPv4 address or 4 first bytes of MD5 hash of IPv6
*/
uint32_t refid;
- uint8_t leap;
+ uint8_t ntp_status;
/* precision is defined as the larger of the resolution and time to
* read the clock, in log2 units. For instance, the precision of a
* mains-frequency clock incrementing at 60 Hz is 16 ms, even when the
@@ -245,8 +245,6 @@ struct globals {
#define G_precision_sec (1.0 / (1 << (- G_precision_exp)))
uint8_t stratum;
/* Bool. After set to 1, never goes back to 0: */
-//TODO: fix logic:
-// uint8_t time_was_stepped;
uint8_t adjtimex_was_done;
uint8_t discipline_state; // doc calls it c.state
@@ -415,12 +413,13 @@ filter_datapoints(peer_t *p, double t)
*/
wavg = 0;
w = 0.5;
- // n-1
- // --- dispersion(i)
- // filter_dispersion = \ -------------
- // / (i+1)
- // --- 2
- // i=0
+ /* n-1
+ * --- dispersion(i)
+ * filter_dispersion = \ -------------
+ * / (i+1)
+ * --- 2
+ * i=0
+ */
got_newest = 0;
sum = 0;
for (i = 0; i < NUM_DATAPOINTS; i++) {
@@ -474,21 +473,22 @@ filter_datapoints(peer_t *p, double t)
}
p->filter_offset = wavg;
- // +----- -----+ ^ 1/2
- // | n-1 |
- // | --- |
- // 1 | \ 2 |
- // filter_jitter = --- * | / (avg-offset_j) |
- // n | --- |
- // | j=0 |
- // +----- -----+
- // where n is the number of valid datapoints in the filter (n > 1);
- // if filter_jitter < precision then filter_jitter = precision
+ /* +----- -----+ ^ 1/2
+ * | n-1 |
+ * | --- |
+ * | 1 \ 2 |
+ * filter_jitter = | --- * / (avg-offset_j) |
+ * | n --- |
+ * | j=0 |
+ * +----- -----+
+ * where n is the number of valid datapoints in the filter (n > 1);
+ * if filter_jitter < precision then filter_jitter = precision
+ */
sum = 0;
for (i = 0; i < NUM_DATAPOINTS; i++) {
sum += SQUARE(wavg - p->filter_datapoint[i].d_offset);
}
- sum = SQRT(sum) / NUM_DATAPOINTS;
+ sum = SQRT(sum / NUM_DATAPOINTS);
p->filter_jitter = sum > G_precision_sec ? sum : G_precision_sec;
VERB3 bb_error_msg("filter offset:%f(corr:%e) disp:%f jitter:%f",
@@ -570,22 +570,23 @@ do_sendto(int fd,
static int
send_query_to_peer(peer_t *p)
{
- // Why do we need to bind()?
- // See what happens when we don't bind:
- //
- // socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
- // setsockopt(3, SOL_IP, IP_TOS, [16], 4) = 0
- // gettimeofday({1259071266, 327885}, NULL) = 0
- // sendto(3, "xxx", 48, MSG_DONTWAIT, {sa_family=AF_INET, sin_port=htons(123), sin_addr=inet_addr("10.34.32.125")}, 16) = 48
- // ^^^ we sent it from some source port picked by kernel.
- // time(NULL) = 1259071266
- // write(2, "ntpd: entering poll 15 secs\n", 28) = 28
- // poll([{fd=3, events=POLLIN}], 1, 15000) = 1 ([{fd=3, revents=POLLIN}])
- // recv(3, "yyy", 68, MSG_DONTWAIT) = 48
- // ^^^ this recv will receive packets to any local port!
- //
- // Uncomment this and use strace to see it in action:
-#define PROBE_LOCAL_ADDR // { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); }
+ /* Why do we need to bind()?
+ * See what happens when we don't bind:
+ *
+ * socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
+ * setsockopt(3, SOL_IP, IP_TOS, [16], 4) = 0
+ * gettimeofday({1259071266, 327885}, NULL) = 0
+ * sendto(3, "xxx", 48, MSG_DONTWAIT, {sa_family=AF_INET, sin_port=htons(123), sin_addr=inet_addr("10.34.32.125")}, 16) = 48
+ * ^^^ we sent it from some source port picked by kernel.
+ * time(NULL) = 1259071266
+ * write(2, "ntpd: entering poll 15 secs\n", 28) = 28
+ * poll([{fd=3, events=POLLIN}], 1, 15000) = 1 ([{fd=3, revents=POLLIN}])
+ * recv(3, "yyy", 68, MSG_DONTWAIT) = 48
+ * ^^^ this recv will receive packets to any local port!
+ *
+ * Uncomment this and use strace to see it in action:
+ */
+#define PROBE_LOCAL_ADDR /* { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); } */
if (p->p_fd == -1) {
int fd, family;
@@ -662,8 +663,6 @@ step_time(double offset)
strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", localtime(&tval));
bb_error_msg("setting clock to %s (offset %fs)", buf, offset);
-
-// G.time_was_stepped = 1;
}
@@ -705,13 +704,14 @@ fit(peer_t *p, double rd)
VERB3 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted);
return 0;
}
-//TODO: we never accept such packets anyway, right?
- if ((p->lastpkt_leap & LI_ALARM) == LI_ALARM
+#if 0 /* we filter out such packets earlier */
+ if ((p->lastpkt_status & LI_ALARM) == LI_ALARM
|| p->lastpkt_stratum >= MAXSTRAT
) {
VERB3 bb_error_msg("peer %s unfit for selection: bad status/stratum", p->p_dotted);
return 0;
}
+#endif
/* rd is root_distance(p, t) */
if (rd > MAXDIST + FREQ_TOLERANCE * (1 << G.poll_exp)) {
VERB3 bb_error_msg("peer %s unfit for selection: root distance too high", p->p_dotted);
@@ -908,7 +908,6 @@ select_and_cluster(double t)
selection_jitter_sq = 0;
for (j = 0; j < num_survivors; j++) {
peer_t *q = survivor[j].p;
-//TODO: where is 1/(n-1) * ... multiplier?
selection_jitter_sq += SQUARE(p->filter_offset - q->filter_offset);
}
if (i == 0 || selection_jitter_sq > max_selection_jitter) {
@@ -918,7 +917,7 @@ select_and_cluster(double t)
VERB5 bb_error_msg("survivor %d selection_jitter^2:%f",
i, selection_jitter_sq);
}
- max_selection_jitter = SQRT(max_selection_jitter);
+ max_selection_jitter = SQRT(max_selection_jitter / num_survivors);
VERB4 bb_error_msg("max_selection_jitter (at %d):%f min_jitter:%f",
max_idx, max_selection_jitter, min_jitter);
@@ -991,7 +990,9 @@ update_local_clock(peer_t *p, double t)
double offset = p->filter_offset;
double recv_time = p->lastpkt_recv_time;
double abs_offset;
+#if !USING_KERNEL_PLL_LOOP
double freq_drift;
+#endif
double since_last_update;
double etemp, dtemp;
@@ -1017,7 +1018,9 @@ update_local_clock(peer_t *p, double t)
* and frequency errors.
*/
since_last_update = recv_time - G.reftime;
+#if !USING_KERNEL_PLL_LOOP
freq_drift = 0;
+#endif
if (G.discipline_state == STATE_FREQ) {
/* Ignore updates until the stepout threshold */
if (since_last_update < WATCH_THRESHOLD) {
@@ -1025,7 +1028,9 @@ update_local_clock(peer_t *p, double t)
WATCH_THRESHOLD - since_last_update);
return 0; /* "leave poll interval as is" */
}
+#if !USING_KERNEL_PLL_LOOP
freq_drift = (offset - G.last_update_offset) / since_last_update;
+#endif
}
/* There are two main regimes: when the
@@ -1145,6 +1150,7 @@ update_local_clock(peer_t *p, double t)
break;
default:
+#if !USING_KERNEL_PLL_LOOP
/* Compute freq_drift due to PLL and FLL contributions.
*
* The FLL and PLL frequency gain constants
@@ -1167,6 +1173,7 @@ update_local_clock(peer_t *p, double t)
etemp = MIND(since_last_update, (1 << G.poll_exp));
dtemp = (4 * PLL) << G.poll_exp;
freq_drift += offset * etemp / SQUARE(dtemp);
+#endif
set_new_values(STATE_SYNC, offset, recv_time);
break;
}
@@ -1174,7 +1181,7 @@ update_local_clock(peer_t *p, double t)
}
G.reftime = t;
- G.leap = p->lastpkt_leap;
+ G.ntp_status = p->lastpkt_status;
G.refid = p->lastpkt_refid;
G.rootdelay = p->lastpkt_rootdelay + p->lastpkt_delay;
dtemp = p->filter_jitter; // SQRT(SQUARE(p->filter_jitter) + SQUARE(s.jitter));
@@ -1241,10 +1248,10 @@ update_local_clock(peer_t *p, double t)
/* + (G.last_update_offset < 0 ? -0.5 : 0.5) - too small to bother */
+ old_tmx_offset; /* almost always 0 */
tmx.status = STA_PLL;
- //if (sys_leap == LEAP_ADDSECOND)
- // tmx.status |= STA_INS;
- //else if (sys_leap == LEAP_DELSECOND)
- // tmx.status |= STA_DEL;
+ if (G.ntp_status & LI_PLUSSEC)
+ tmx.status |= STA_INS;
+ if (G.ntp_status & LI_MINUSSEC)
+ tmx.status |= STA_DEL;
tmx.constant = G.poll_exp - 4;
//tmx.esterror = (u_int32)(clock_jitter * 1e6);
//tmx.maxerror = (u_int32)((sys_rootdelay / 2 + sys_rootdisp) * 1e6);
@@ -1376,18 +1383,12 @@ recv_and_process_peer_pkt(peer_t *p)
goto close_sock;
}
-// /*
-// * Verify the server is synchronized with valid stratum and
-// * reference time not later than the transmit time.
-// */
-// if (p->lastpkt_leap == NOSYNC || p->lastpkt_stratum >= MAXSTRAT)
-// return; /* unsynchronized */
-//
// /* Verify valid root distance */
// if (msg.m_rootdelay / 2 + msg.m_rootdisp >= MAXDISP || p->lastpkt_reftime > msg.m_xmt)
// return; /* invalid header values */
- p->lastpkt_leap = msg.m_status;
+ 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;
@@ -1557,7 +1558,7 @@ recv_and_process_client_pkt(void /*int fd*/)
/* Build a reply packet */
memset(&msg, 0, sizeof(msg));
- msg.m_status = G.stratum < MAXSTRAT ? G.leap : LI_ALARM;
+ msg.m_status = G.stratum < MAXSTRAT ? G.ntp_status : LI_ALARM;
msg.m_status |= (query_status & VERSION_MASK);
msg.m_status |= ((query_status & MODE_MASK) == MODE_CLIENT) ?
MODE_SERVER : MODE_SYM_PAS;
@@ -1822,10 +1823,6 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
}
}
-// if ((trial_cnt > 0 && sent_cnt == 0) || g.peer_cnt == 0) {
-// G.time_was_stepped = 1;
-// }
-
timeout = nextaction - cur_time;
if (timeout < 1)
timeout = 1;