aboutsummaryrefslogtreecommitdiff
path: root/networking/ntpd.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-01-02 15:57:07 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-01-02 15:57:07 +0100
commit1ee5afdce28d5a11987071f710c1d2fd493618cc (patch)
treef6de1959d1c5ffc8b74c5a3f1940498602140be6 /networking/ntpd.c
parentf25252c69e4b46917daa799d2ebe4b4f4da9410d (diff)
downloadbusybox-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.c119
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,
570static int 570static int
571send_query_to_peer(peer_t *p) 571send_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;