diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-02 15:57:07 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-02 15:57:07 +0100 |
commit | 1ee5afdce28d5a11987071f710c1d2fd493618cc (patch) | |
tree | f6de1959d1c5ffc8b74c5a3f1940498602140be6 /networking/ntpd.c | |
parent | f25252c69e4b46917daa799d2ebe4b4f4da9410d (diff) | |
download | busybox-w32-1ee5afdce28d5a11987071f710c1d2fd493618cc.tar.gz busybox-w32-1ee5afdce28d5a11987071f710c1d2fd493618cc.tar.bz2 busybox-w32-1ee5afdce28d5a11987071f710c1d2fd493618cc.zip |
ntpd: fix jitter calculations and status propagation
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/ntpd.c')
-rw-r--r-- | networking/ntpd.c | 119 |
1 files changed, 58 insertions, 61 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c index cabfb795a..92e2723a5 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -166,7 +166,7 @@ typedef struct { | |||
166 | int p_fd; | 166 | int p_fd; |
167 | int datapoint_idx; | 167 | int datapoint_idx; |
168 | uint32_t lastpkt_refid; | 168 | uint32_t lastpkt_refid; |
169 | uint8_t lastpkt_leap; | 169 | uint8_t lastpkt_status; |
170 | uint8_t lastpkt_stratum; | 170 | uint8_t lastpkt_stratum; |
171 | uint8_t p_reachable_bits; | 171 | uint8_t p_reachable_bits; |
172 | double p_xmttime; | 172 | double p_xmttime; |
@@ -216,7 +216,7 @@ struct globals { | |||
216 | * in stratum 2+ packets, it's IPv4 address or 4 first bytes of MD5 hash of IPv6 | 216 | * in stratum 2+ packets, it's IPv4 address or 4 first bytes of MD5 hash of IPv6 |
217 | */ | 217 | */ |
218 | uint32_t refid; | 218 | uint32_t refid; |
219 | uint8_t leap; | 219 | uint8_t ntp_status; |
220 | /* precision is defined as the larger of the resolution and time to | 220 | /* precision is defined as the larger of the resolution and time to |
221 | * read the clock, in log2 units. For instance, the precision of a | 221 | * read the clock, in log2 units. For instance, the precision of a |
222 | * mains-frequency clock incrementing at 60 Hz is 16 ms, even when the | 222 | * mains-frequency clock incrementing at 60 Hz is 16 ms, even when the |
@@ -245,8 +245,6 @@ struct globals { | |||
245 | #define G_precision_sec (1.0 / (1 << (- G_precision_exp))) | 245 | #define G_precision_sec (1.0 / (1 << (- G_precision_exp))) |
246 | uint8_t stratum; | 246 | uint8_t stratum; |
247 | /* Bool. After set to 1, never goes back to 0: */ | 247 | /* Bool. After set to 1, never goes back to 0: */ |
248 | //TODO: fix logic: | ||
249 | // uint8_t time_was_stepped; | ||
250 | uint8_t adjtimex_was_done; | 248 | uint8_t adjtimex_was_done; |
251 | 249 | ||
252 | uint8_t discipline_state; // doc calls it c.state | 250 | uint8_t discipline_state; // doc calls it c.state |
@@ -415,12 +413,13 @@ filter_datapoints(peer_t *p, double t) | |||
415 | */ | 413 | */ |
416 | wavg = 0; | 414 | wavg = 0; |
417 | w = 0.5; | 415 | w = 0.5; |
418 | // n-1 | 416 | /* n-1 |
419 | // --- dispersion(i) | 417 | * --- dispersion(i) |
420 | // filter_dispersion = \ ------------- | 418 | * filter_dispersion = \ ------------- |
421 | // / (i+1) | 419 | * / (i+1) |
422 | // --- 2 | 420 | * --- 2 |
423 | // i=0 | 421 | * i=0 |
422 | */ | ||
424 | got_newest = 0; | 423 | got_newest = 0; |
425 | sum = 0; | 424 | sum = 0; |
426 | for (i = 0; i < NUM_DATAPOINTS; i++) { | 425 | for (i = 0; i < NUM_DATAPOINTS; i++) { |
@@ -474,21 +473,22 @@ filter_datapoints(peer_t *p, double t) | |||
474 | } | 473 | } |
475 | p->filter_offset = wavg; | 474 | p->filter_offset = wavg; |
476 | 475 | ||
477 | // +----- -----+ ^ 1/2 | 476 | /* +----- -----+ ^ 1/2 |
478 | // | n-1 | | 477 | * | n-1 | |
479 | // | --- | | 478 | * | --- | |
480 | // 1 | \ 2 | | 479 | * | 1 \ 2 | |
481 | // filter_jitter = --- * | / (avg-offset_j) | | 480 | * filter_jitter = | --- * / (avg-offset_j) | |
482 | // n | --- | | 481 | * | n --- | |
483 | // | j=0 | | 482 | * | j=0 | |
484 | // +----- -----+ | 483 | * +----- -----+ |
485 | // where n is the number of valid datapoints in the filter (n > 1); | 484 | * where n is the number of valid datapoints in the filter (n > 1); |
486 | // if filter_jitter < precision then filter_jitter = precision | 485 | * if filter_jitter < precision then filter_jitter = precision |
486 | */ | ||
487 | sum = 0; | 487 | sum = 0; |
488 | for (i = 0; i < NUM_DATAPOINTS; i++) { | 488 | for (i = 0; i < NUM_DATAPOINTS; i++) { |
489 | sum += SQUARE(wavg - p->filter_datapoint[i].d_offset); | 489 | sum += SQUARE(wavg - p->filter_datapoint[i].d_offset); |
490 | } | 490 | } |
491 | sum = SQRT(sum) / NUM_DATAPOINTS; | 491 | sum = SQRT(sum / NUM_DATAPOINTS); |
492 | p->filter_jitter = sum > G_precision_sec ? sum : G_precision_sec; | 492 | p->filter_jitter = sum > G_precision_sec ? sum : G_precision_sec; |
493 | 493 | ||
494 | VERB3 bb_error_msg("filter offset:%f(corr:%e) disp:%f jitter:%f", | 494 | VERB3 bb_error_msg("filter offset:%f(corr:%e) disp:%f jitter:%f", |
@@ -570,22 +570,23 @@ do_sendto(int fd, | |||
570 | static int | 570 | static int |
571 | send_query_to_peer(peer_t *p) | 571 | send_query_to_peer(peer_t *p) |
572 | { | 572 | { |
573 | // Why do we need to bind()? | 573 | /* Why do we need to bind()? |
574 | // See what happens when we don't bind: | 574 | * See what happens when we don't bind: |
575 | // | 575 | * |
576 | // socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3 | 576 | * socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3 |
577 | // setsockopt(3, SOL_IP, IP_TOS, [16], 4) = 0 | 577 | * setsockopt(3, SOL_IP, IP_TOS, [16], 4) = 0 |
578 | // gettimeofday({1259071266, 327885}, NULL) = 0 | 578 | * gettimeofday({1259071266, 327885}, NULL) = 0 |
579 | // sendto(3, "xxx", 48, MSG_DONTWAIT, {sa_family=AF_INET, sin_port=htons(123), sin_addr=inet_addr("10.34.32.125")}, 16) = 48 | 579 | * sendto(3, "xxx", 48, MSG_DONTWAIT, {sa_family=AF_INET, sin_port=htons(123), sin_addr=inet_addr("10.34.32.125")}, 16) = 48 |
580 | // ^^^ we sent it from some source port picked by kernel. | 580 | * ^^^ we sent it from some source port picked by kernel. |
581 | // time(NULL) = 1259071266 | 581 | * time(NULL) = 1259071266 |
582 | // write(2, "ntpd: entering poll 15 secs\n", 28) = 28 | 582 | * write(2, "ntpd: entering poll 15 secs\n", 28) = 28 |
583 | // poll([{fd=3, events=POLLIN}], 1, 15000) = 1 ([{fd=3, revents=POLLIN}]) | 583 | * poll([{fd=3, events=POLLIN}], 1, 15000) = 1 ([{fd=3, revents=POLLIN}]) |
584 | // recv(3, "yyy", 68, MSG_DONTWAIT) = 48 | 584 | * recv(3, "yyy", 68, MSG_DONTWAIT) = 48 |
585 | // ^^^ this recv will receive packets to any local port! | 585 | * ^^^ this recv will receive packets to any local port! |
586 | // | 586 | * |
587 | // Uncomment this and use strace to see it in action: | 587 | * Uncomment this and use strace to see it in action: |
588 | #define PROBE_LOCAL_ADDR // { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); } | 588 | */ |
589 | #define PROBE_LOCAL_ADDR /* { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); } */ | ||
589 | 590 | ||
590 | if (p->p_fd == -1) { | 591 | if (p->p_fd == -1) { |
591 | int fd, family; | 592 | int fd, family; |
@@ -662,8 +663,6 @@ step_time(double offset) | |||
662 | strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", localtime(&tval)); | 663 | strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", localtime(&tval)); |
663 | 664 | ||
664 | bb_error_msg("setting clock to %s (offset %fs)", buf, offset); | 665 | bb_error_msg("setting clock to %s (offset %fs)", buf, offset); |
665 | |||
666 | // G.time_was_stepped = 1; | ||
667 | } | 666 | } |
668 | 667 | ||
669 | 668 | ||
@@ -705,13 +704,14 @@ fit(peer_t *p, double rd) | |||
705 | VERB3 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted); | 704 | VERB3 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted); |
706 | return 0; | 705 | return 0; |
707 | } | 706 | } |
708 | //TODO: we never accept such packets anyway, right? | 707 | #if 0 /* we filter out such packets earlier */ |
709 | if ((p->lastpkt_leap & LI_ALARM) == LI_ALARM | 708 | if ((p->lastpkt_status & LI_ALARM) == LI_ALARM |
710 | || p->lastpkt_stratum >= MAXSTRAT | 709 | || p->lastpkt_stratum >= MAXSTRAT |
711 | ) { | 710 | ) { |
712 | VERB3 bb_error_msg("peer %s unfit for selection: bad status/stratum", p->p_dotted); | 711 | VERB3 bb_error_msg("peer %s unfit for selection: bad status/stratum", p->p_dotted); |
713 | return 0; | 712 | return 0; |
714 | } | 713 | } |
714 | #endif | ||
715 | /* rd is root_distance(p, t) */ | 715 | /* rd is root_distance(p, t) */ |
716 | if (rd > MAXDIST + FREQ_TOLERANCE * (1 << G.poll_exp)) { | 716 | if (rd > MAXDIST + FREQ_TOLERANCE * (1 << G.poll_exp)) { |
717 | VERB3 bb_error_msg("peer %s unfit for selection: root distance too high", p->p_dotted); | 717 | 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) | |||
908 | selection_jitter_sq = 0; | 908 | selection_jitter_sq = 0; |
909 | for (j = 0; j < num_survivors; j++) { | 909 | for (j = 0; j < num_survivors; j++) { |
910 | peer_t *q = survivor[j].p; | 910 | peer_t *q = survivor[j].p; |
911 | //TODO: where is 1/(n-1) * ... multiplier? | ||
912 | selection_jitter_sq += SQUARE(p->filter_offset - q->filter_offset); | 911 | selection_jitter_sq += SQUARE(p->filter_offset - q->filter_offset); |
913 | } | 912 | } |
914 | if (i == 0 || selection_jitter_sq > max_selection_jitter) { | 913 | if (i == 0 || selection_jitter_sq > max_selection_jitter) { |
@@ -918,7 +917,7 @@ select_and_cluster(double t) | |||
918 | VERB5 bb_error_msg("survivor %d selection_jitter^2:%f", | 917 | VERB5 bb_error_msg("survivor %d selection_jitter^2:%f", |
919 | i, selection_jitter_sq); | 918 | i, selection_jitter_sq); |
920 | } | 919 | } |
921 | max_selection_jitter = SQRT(max_selection_jitter); | 920 | max_selection_jitter = SQRT(max_selection_jitter / num_survivors); |
922 | VERB4 bb_error_msg("max_selection_jitter (at %d):%f min_jitter:%f", | 921 | VERB4 bb_error_msg("max_selection_jitter (at %d):%f min_jitter:%f", |
923 | max_idx, max_selection_jitter, min_jitter); | 922 | max_idx, max_selection_jitter, min_jitter); |
924 | 923 | ||
@@ -991,7 +990,9 @@ update_local_clock(peer_t *p, double t) | |||
991 | double offset = p->filter_offset; | 990 | double offset = p->filter_offset; |
992 | double recv_time = p->lastpkt_recv_time; | 991 | double recv_time = p->lastpkt_recv_time; |
993 | double abs_offset; | 992 | double abs_offset; |
993 | #if !USING_KERNEL_PLL_LOOP | ||
994 | double freq_drift; | 994 | double freq_drift; |
995 | #endif | ||
995 | double since_last_update; | 996 | double since_last_update; |
996 | double etemp, dtemp; | 997 | double etemp, dtemp; |
997 | 998 | ||
@@ -1017,7 +1018,9 @@ update_local_clock(peer_t *p, double t) | |||
1017 | * and frequency errors. | 1018 | * and frequency errors. |
1018 | */ | 1019 | */ |
1019 | since_last_update = recv_time - G.reftime; | 1020 | since_last_update = recv_time - G.reftime; |
1021 | #if !USING_KERNEL_PLL_LOOP | ||
1020 | freq_drift = 0; | 1022 | freq_drift = 0; |
1023 | #endif | ||
1021 | if (G.discipline_state == STATE_FREQ) { | 1024 | if (G.discipline_state == STATE_FREQ) { |
1022 | /* Ignore updates until the stepout threshold */ | 1025 | /* Ignore updates until the stepout threshold */ |
1023 | if (since_last_update < WATCH_THRESHOLD) { | 1026 | if (since_last_update < WATCH_THRESHOLD) { |
@@ -1025,7 +1028,9 @@ update_local_clock(peer_t *p, double t) | |||
1025 | WATCH_THRESHOLD - since_last_update); | 1028 | WATCH_THRESHOLD - since_last_update); |
1026 | return 0; /* "leave poll interval as is" */ | 1029 | return 0; /* "leave poll interval as is" */ |
1027 | } | 1030 | } |
1031 | #if !USING_KERNEL_PLL_LOOP | ||
1028 | freq_drift = (offset - G.last_update_offset) / since_last_update; | 1032 | freq_drift = (offset - G.last_update_offset) / since_last_update; |
1033 | #endif | ||
1029 | } | 1034 | } |
1030 | 1035 | ||
1031 | /* There are two main regimes: when the | 1036 | /* There are two main regimes: when the |
@@ -1145,6 +1150,7 @@ update_local_clock(peer_t *p, double t) | |||
1145 | break; | 1150 | break; |
1146 | 1151 | ||
1147 | default: | 1152 | default: |
1153 | #if !USING_KERNEL_PLL_LOOP | ||
1148 | /* Compute freq_drift due to PLL and FLL contributions. | 1154 | /* Compute freq_drift due to PLL and FLL contributions. |
1149 | * | 1155 | * |
1150 | * The FLL and PLL frequency gain constants | 1156 | * The FLL and PLL frequency gain constants |
@@ -1167,6 +1173,7 @@ update_local_clock(peer_t *p, double t) | |||
1167 | etemp = MIND(since_last_update, (1 << G.poll_exp)); | 1173 | etemp = MIND(since_last_update, (1 << G.poll_exp)); |
1168 | dtemp = (4 * PLL) << G.poll_exp; | 1174 | dtemp = (4 * PLL) << G.poll_exp; |
1169 | freq_drift += offset * etemp / SQUARE(dtemp); | 1175 | freq_drift += offset * etemp / SQUARE(dtemp); |
1176 | #endif | ||
1170 | set_new_values(STATE_SYNC, offset, recv_time); | 1177 | set_new_values(STATE_SYNC, offset, recv_time); |
1171 | break; | 1178 | break; |
1172 | } | 1179 | } |
@@ -1174,7 +1181,7 @@ update_local_clock(peer_t *p, double t) | |||
1174 | } | 1181 | } |
1175 | 1182 | ||
1176 | G.reftime = t; | 1183 | G.reftime = t; |
1177 | G.leap = p->lastpkt_leap; | 1184 | G.ntp_status = p->lastpkt_status; |
1178 | G.refid = p->lastpkt_refid; | 1185 | G.refid = p->lastpkt_refid; |
1179 | G.rootdelay = p->lastpkt_rootdelay + p->lastpkt_delay; | 1186 | G.rootdelay = p->lastpkt_rootdelay + p->lastpkt_delay; |
1180 | dtemp = p->filter_jitter; // SQRT(SQUARE(p->filter_jitter) + SQUARE(s.jitter)); | 1187 | dtemp = p->filter_jitter; // SQRT(SQUARE(p->filter_jitter) + SQUARE(s.jitter)); |
@@ -1241,10 +1248,10 @@ update_local_clock(peer_t *p, double t) | |||
1241 | /* + (G.last_update_offset < 0 ? -0.5 : 0.5) - too small to bother */ | 1248 | /* + (G.last_update_offset < 0 ? -0.5 : 0.5) - too small to bother */ |
1242 | + old_tmx_offset; /* almost always 0 */ | 1249 | + old_tmx_offset; /* almost always 0 */ |
1243 | tmx.status = STA_PLL; | 1250 | tmx.status = STA_PLL; |
1244 | //if (sys_leap == LEAP_ADDSECOND) | 1251 | if (G.ntp_status & LI_PLUSSEC) |
1245 | // tmx.status |= STA_INS; | 1252 | tmx.status |= STA_INS; |
1246 | //else if (sys_leap == LEAP_DELSECOND) | 1253 | if (G.ntp_status & LI_MINUSSEC) |
1247 | // tmx.status |= STA_DEL; | 1254 | tmx.status |= STA_DEL; |
1248 | tmx.constant = G.poll_exp - 4; | 1255 | tmx.constant = G.poll_exp - 4; |
1249 | //tmx.esterror = (u_int32)(clock_jitter * 1e6); | 1256 | //tmx.esterror = (u_int32)(clock_jitter * 1e6); |
1250 | //tmx.maxerror = (u_int32)((sys_rootdelay / 2 + sys_rootdisp) * 1e6); | 1257 | //tmx.maxerror = (u_int32)((sys_rootdelay / 2 + sys_rootdisp) * 1e6); |
@@ -1376,18 +1383,12 @@ recv_and_process_peer_pkt(peer_t *p) | |||
1376 | goto close_sock; | 1383 | goto close_sock; |
1377 | } | 1384 | } |
1378 | 1385 | ||
1379 | // /* | ||
1380 | // * Verify the server is synchronized with valid stratum and | ||
1381 | // * reference time not later than the transmit time. | ||
1382 | // */ | ||
1383 | // if (p->lastpkt_leap == NOSYNC || p->lastpkt_stratum >= MAXSTRAT) | ||
1384 | // return; /* unsynchronized */ | ||
1385 | // | ||
1386 | // /* Verify valid root distance */ | 1386 | // /* Verify valid root distance */ |
1387 | // if (msg.m_rootdelay / 2 + msg.m_rootdisp >= MAXDISP || p->lastpkt_reftime > msg.m_xmt) | 1387 | // if (msg.m_rootdelay / 2 + msg.m_rootdisp >= MAXDISP || p->lastpkt_reftime > msg.m_xmt) |
1388 | // return; /* invalid header values */ | 1388 | // return; /* invalid header values */ |
1389 | 1389 | ||
1390 | p->lastpkt_leap = msg.m_status; | 1390 | p->lastpkt_status = msg.m_status; |
1391 | p->lastpkt_stratum = msg.m_stratum; | ||
1391 | p->lastpkt_rootdelay = sfp_to_d(msg.m_rootdelay); | 1392 | p->lastpkt_rootdelay = sfp_to_d(msg.m_rootdelay); |
1392 | p->lastpkt_rootdisp = sfp_to_d(msg.m_rootdisp); | 1393 | p->lastpkt_rootdisp = sfp_to_d(msg.m_rootdisp); |
1393 | p->lastpkt_refid = msg.m_refid; | 1394 | p->lastpkt_refid = msg.m_refid; |
@@ -1557,7 +1558,7 @@ recv_and_process_client_pkt(void /*int fd*/) | |||
1557 | 1558 | ||
1558 | /* Build a reply packet */ | 1559 | /* Build a reply packet */ |
1559 | memset(&msg, 0, sizeof(msg)); | 1560 | memset(&msg, 0, sizeof(msg)); |
1560 | msg.m_status = G.stratum < MAXSTRAT ? G.leap : LI_ALARM; | 1561 | msg.m_status = G.stratum < MAXSTRAT ? G.ntp_status : LI_ALARM; |
1561 | msg.m_status |= (query_status & VERSION_MASK); | 1562 | msg.m_status |= (query_status & VERSION_MASK); |
1562 | msg.m_status |= ((query_status & MODE_MASK) == MODE_CLIENT) ? | 1563 | msg.m_status |= ((query_status & MODE_MASK) == MODE_CLIENT) ? |
1563 | MODE_SERVER : MODE_SYM_PAS; | 1564 | MODE_SERVER : MODE_SYM_PAS; |
@@ -1822,10 +1823,6 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) | |||
1822 | } | 1823 | } |
1823 | } | 1824 | } |
1824 | 1825 | ||
1825 | // if ((trial_cnt > 0 && sent_cnt == 0) || g.peer_cnt == 0) { | ||
1826 | // G.time_was_stepped = 1; | ||
1827 | // } | ||
1828 | |||
1829 | timeout = nextaction - cur_time; | 1826 | timeout = nextaction - cur_time; |
1830 | if (timeout < 1) | 1827 | if (timeout < 1) |
1831 | timeout = 1; | 1828 | timeout = 1; |