aboutsummaryrefslogtreecommitdiff
path: root/networking/ntpd.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-01-03 08:59:59 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-01-03 08:59:59 +0100
commit0b002812a8c2a95ab18374452fd0ab2065ed4029 (patch)
tree2a942698ee6d8597e2b867d8da453f47979dae79 /networking/ntpd.c
parent185e691ec129f9dc0c7150348766b86da08c1abb (diff)
downloadbusybox-w32-0b002812a8c2a95ab18374452fd0ab2065ed4029.tar.gz
busybox-w32-0b002812a8c2a95ab18374452fd0ab2065ed4029.tar.bz2
busybox-w32-0b002812a8c2a95ab18374452fd0ab2065ed4029.zip
ntpd: better selection of initial sync; fewer gettimeofday calls
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/ntpd.c')
-rw-r--r--networking/ntpd.c252
1 files changed, 126 insertions, 126 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 92e2723a5..520dcd16b 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -47,9 +47,10 @@
47 47
48 48
49#define RETRY_INTERVAL 5 /* on error, retry in N secs */ 49#define RETRY_INTERVAL 5 /* on error, retry in N secs */
50#define QUERYTIME_MAX 15 /* wait for reply up to N secs */ 50#define RESPONSE_INTERVAL 15 /* wait for reply up to N secs */
51 51
52#define FREQ_TOLERANCE 0.000015 /* % frequency tolerance (15 PPM) */ 52#define FREQ_TOLERANCE 0.000015 /* % frequency tolerance (15 PPM) */
53#define BURSTPOLL 0
53#define MINPOLL 4 /* % minimum poll interval (6: 64 s) */ 54#define MINPOLL 4 /* % minimum poll interval (6: 64 s) */
54#define MAXPOLL 12 /* % maximum poll interval (12: 1.1h, 17: 36.4h) (was 17) */ 55#define MAXPOLL 12 /* % maximum poll interval (12: 1.1h, 17: 36.4h) (was 17) */
55#define MINDISP 0.01 /* % minimum dispersion (s) */ 56#define MINDISP 0.01 /* % minimum dispersion (s) */
@@ -162,13 +163,13 @@ typedef struct {
162 char *p_dotted; 163 char *p_dotted;
163 /* when to send new query (if p_fd == -1) 164 /* when to send new query (if p_fd == -1)
164 * or when receive times out (if p_fd >= 0): */ 165 * or when receive times out (if p_fd >= 0): */
165 time_t next_action_time;
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_status; 169 uint8_t lastpkt_status;
170 uint8_t lastpkt_stratum; 170 uint8_t lastpkt_stratum;
171 uint8_t p_reachable_bits; 171 uint8_t reachable_bits;
172 double next_action_time;
172 double p_xmttime; 173 double p_xmttime;
173 double lastpkt_recv_time; 174 double lastpkt_recv_time;
174 double lastpkt_delay; 175 double lastpkt_delay;
@@ -196,6 +197,7 @@ enum {
196}; 197};
197 198
198struct globals { 199struct globals {
200 double cur_time;
199 /* total round trip delay to currently selected reference clock */ 201 /* total round trip delay to currently selected reference clock */
200 double rootdelay; 202 double rootdelay;
201 /* reference timestamp: time when the system clock was last set or corrected */ 203 /* reference timestamp: time when the system clock was last set or corrected */
@@ -245,7 +247,8 @@ struct globals {
245#define G_precision_sec (1.0 / (1 << (- G_precision_exp))) 247#define G_precision_sec (1.0 / (1 << (- G_precision_exp)))
246 uint8_t stratum; 248 uint8_t stratum;
247 /* Bool. After set to 1, never goes back to 0: */ 249 /* Bool. After set to 1, never goes back to 0: */
248 uint8_t adjtimex_was_done; 250 smallint adjtimex_was_done;
251 smallint initial_poll_complete;
249 252
250 uint8_t discipline_state; // doc calls it c.state 253 uint8_t discipline_state; // doc calls it c.state
251 uint8_t poll_exp; // s.poll 254 uint8_t poll_exp; // s.poll
@@ -303,7 +306,8 @@ gettime1900d(void)
303{ 306{
304 struct timeval tv; 307 struct timeval tv;
305 gettimeofday(&tv, NULL); /* never fails */ 308 gettimeofday(&tv, NULL); /* never fails */
306 return (tv.tv_sec + 1.0e-6 * tv.tv_usec + OFFSET_1900_1970); 309 G.cur_time = tv.tv_sec + (1.0e-6 * tv.tv_usec) + OFFSET_1900_1970;
310 return G.cur_time;
307} 311}
308 312
309static void 313static void
@@ -355,13 +359,13 @@ d_to_sfp(double d)
355#endif 359#endif
356 360
357static double 361static double
358dispersion(const datapoint_t *dp, double t) 362dispersion(const datapoint_t *dp)
359{ 363{
360 return dp->d_dispersion + FREQ_TOLERANCE * (t - dp->d_recv_time); 364 return dp->d_dispersion + FREQ_TOLERANCE * (G.cur_time - dp->d_recv_time);
361} 365}
362 366
363static double 367static double
364root_distance(peer_t *p, double t) 368root_distance(peer_t *p)
365{ 369{
366 /* The root synchronization distance is the maximum error due to 370 /* The root synchronization distance is the maximum error due to
367 * all causes of the local clock relative to the primary server. 371 * all causes of the local clock relative to the primary server.
@@ -371,21 +375,21 @@ root_distance(peer_t *p, double t)
371 return MAXD(MINDISP, p->lastpkt_rootdelay + p->lastpkt_delay) / 2 375 return MAXD(MINDISP, p->lastpkt_rootdelay + p->lastpkt_delay) / 2
372 + p->lastpkt_rootdisp 376 + p->lastpkt_rootdisp
373 + p->filter_dispersion 377 + p->filter_dispersion
374 + FREQ_TOLERANCE * (t - p->lastpkt_recv_time) 378 + FREQ_TOLERANCE * (G.cur_time - p->lastpkt_recv_time)
375 + p->filter_jitter; 379 + p->filter_jitter;
376} 380}
377 381
378static void 382static void
379set_next(peer_t *p, unsigned t) 383set_next(peer_t *p, unsigned t)
380{ 384{
381 p->next_action_time = time(NULL) + t; 385 p->next_action_time = G.cur_time + t;
382} 386}
383 387
384/* 388/*
385 * Peer clock filter and its helpers 389 * Peer clock filter and its helpers
386 */ 390 */
387static void 391static void
388filter_datapoints(peer_t *p, double t) 392filter_datapoints(peer_t *p)
389{ 393{
390 int i, idx; 394 int i, idx;
391 int got_newest; 395 int got_newest;
@@ -427,14 +431,14 @@ filter_datapoints(peer_t *p, double t)
427 bb_error_msg("datapoint[%d]: off:%f disp:%f(%f) age:%f%s", 431 bb_error_msg("datapoint[%d]: off:%f disp:%f(%f) age:%f%s",
428 i, 432 i,
429 p->filter_datapoint[idx].d_offset, 433 p->filter_datapoint[idx].d_offset,
430 p->filter_datapoint[idx].d_dispersion, dispersion(&p->filter_datapoint[idx], t), 434 p->filter_datapoint[idx].d_dispersion, dispersion(&p->filter_datapoint[idx]),
431 t - p->filter_datapoint[idx].d_recv_time, 435 G.cur_time - p->filter_datapoint[idx].d_recv_time,
432 (minoff == p->filter_datapoint[idx].d_offset || maxoff == p->filter_datapoint[idx].d_offset) 436 (minoff == p->filter_datapoint[idx].d_offset || maxoff == p->filter_datapoint[idx].d_offset)
433 ? " (outlier by offset)" : "" 437 ? " (outlier by offset)" : ""
434 ); 438 );
435 } 439 }
436 440
437 sum += dispersion(&p->filter_datapoint[idx], t) / (2 << i); 441 sum += dispersion(&p->filter_datapoint[idx]) / (2 << i);
438 442
439 if (minoff == p->filter_datapoint[idx].d_offset) { 443 if (minoff == p->filter_datapoint[idx].d_offset) {
440 minoff -= 1; /* so that we don't match it ever again */ 444 minoff -= 1; /* so that we don't match it ever again */
@@ -443,7 +447,7 @@ filter_datapoints(peer_t *p, double t)
443 maxoff += 1; 447 maxoff += 1;
444 } else { 448 } else {
445 oldest_off = p->filter_datapoint[idx].d_offset; 449 oldest_off = p->filter_datapoint[idx].d_offset;
446 oldest_age = t - p->filter_datapoint[idx].d_recv_time; 450 oldest_age = G.cur_time - p->filter_datapoint[idx].d_recv_time;
447 if (!got_newest) { 451 if (!got_newest) {
448 got_newest = 1; 452 got_newest = 1;
449 newest_off = oldest_off; 453 newest_off = oldest_off;
@@ -466,10 +470,13 @@ filter_datapoints(peer_t *p, double t)
466 * and then we have this estimation, ~25% off from 0.7: 470 * and then we have this estimation, ~25% off from 0.7:
467 * 0.1/32 + 0.2/32 + 0.3/16 + 0.4/8 + 0.5/4 + 0.6/2 = 0.503125 471 * 0.1/32 + 0.2/32 + 0.3/16 + 0.4/8 + 0.5/4 + 0.6/2 = 0.503125
468 */ 472 */
469 x = newest_age / (oldest_age - newest_age); /* in above example, 100 / (600 - 100) */ 473 x = oldest_age - newest_age;
470 if (x < 1) { 474 if (x != 0) {
471 x = (newest_off - oldest_off) * x; /* 0.5 * 100/500 = 0.1 */ 475 x = newest_age / x; /* in above example, 100 / (600 - 100) */
472 wavg += x; 476 if (x < 1) { /* paranoia check */
477 x = (newest_off - oldest_off) * x; /* 0.5 * 100/500 = 0.1 */
478 wavg += x;
479 }
473 } 480 }
474 p->filter_offset = wavg; 481 p->filter_offset = wavg;
475 482
@@ -499,7 +506,7 @@ filter_datapoints(peer_t *p, double t)
499} 506}
500 507
501static void 508static void
502reset_peer_stats(peer_t *p, double t, double offset) 509reset_peer_stats(peer_t *p, double offset)
503{ 510{
504 int i; 511 int i;
505 for (i = 0; i < NUM_DATAPOINTS; i++) { 512 for (i = 0; i < NUM_DATAPOINTS; i++) {
@@ -509,7 +516,7 @@ reset_peer_stats(peer_t *p, double t, double offset)
509 p->filter_datapoint[i].d_offset -= offset; 516 p->filter_datapoint[i].d_offset -= offset;
510 } 517 }
511 } else { 518 } else {
512 p->filter_datapoint[i].d_recv_time = t; 519 p->filter_datapoint[i].d_recv_time = G.cur_time;
513 p->filter_datapoint[i].d_offset = 0; 520 p->filter_datapoint[i].d_offset = 0;
514 p->filter_datapoint[i].d_dispersion = MAXDISP; 521 p->filter_datapoint[i].d_dispersion = MAXDISP;
515 } 522 }
@@ -517,11 +524,11 @@ reset_peer_stats(peer_t *p, double t, double offset)
517 if (offset < 16 * STEP_THRESHOLD) { 524 if (offset < 16 * STEP_THRESHOLD) {
518 p->lastpkt_recv_time -= offset; 525 p->lastpkt_recv_time -= offset;
519 } else { 526 } else {
520 p->p_reachable_bits = 0; 527 p->reachable_bits = 0;
521 p->lastpkt_recv_time = t; 528 p->lastpkt_recv_time = G.cur_time;
522 } 529 }
523 filter_datapoints(p, t); /* recalc p->filter_xxx */ 530 filter_datapoints(p); /* recalc p->filter_xxx */
524 p->next_action_time -= (time_t)offset; 531 p->next_action_time -= offset;
525 VERB5 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time); 532 VERB5 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
526} 533}
527 534
@@ -535,8 +542,8 @@ add_peers(char *s)
535 p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa); 542 p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa);
536 p->p_fd = -1; 543 p->p_fd = -1;
537 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3); 544 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
538 p->next_action_time = time(NULL); /* = set_next(p, 0); */ 545 p->next_action_time = G.cur_time; /* = set_next(p, 0); */
539 reset_peer_stats(p, gettime1900d(), 16 * STEP_THRESHOLD); 546 reset_peer_stats(p, 16 * STEP_THRESHOLD);
540 /* Speed up initial sync: with small offsets from peers, 547 /* Speed up initial sync: with small offsets from peers,
541 * 3 samples will sync 548 * 3 samples will sync
542 */ 549 */
@@ -567,7 +574,7 @@ do_sendto(int fd,
567 return 0; 574 return 0;
568} 575}
569 576
570static int 577static void
571send_query_to_peer(peer_t *p) 578send_query_to_peer(peer_t *p)
572{ 579{
573 /* Why do we need to bind()? 580 /* Why do we need to bind()?
@@ -632,20 +639,19 @@ send_query_to_peer(peer_t *p)
632 close(p->p_fd); 639 close(p->p_fd);
633 p->p_fd = -1; 640 p->p_fd = -1;
634 set_next(p, RETRY_INTERVAL); 641 set_next(p, RETRY_INTERVAL);
635 return -1; 642 return;
636 } 643 }
637 644
638 p->p_reachable_bits <<= 1; 645 p->reachable_bits <<= 1;
639 VERB1 bb_error_msg("sent query to %s", p->p_dotted); 646 VERB1 bb_error_msg("sent query to %s", p->p_dotted);
640 set_next(p, QUERYTIME_MAX); 647 set_next(p, RESPONSE_INTERVAL);
641
642 return 0;
643} 648}
644 649
645 650
646static void 651static NOINLINE void
647step_time(double offset) 652step_time(double offset)
648{ 653{
654 llist_t *item;
649 double dtime; 655 double dtime;
650 struct timeval tv; 656 struct timeval tv;
651 char buf[80]; 657 char buf[80];
@@ -663,6 +669,17 @@ step_time(double offset)
663 strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", localtime(&tval)); 669 strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", localtime(&tval));
664 670
665 bb_error_msg("setting clock to %s (offset %fs)", buf, offset); 671 bb_error_msg("setting clock to %s (offset %fs)", buf, offset);
672
673 /* Correct various fields which contain time-relative values: */
674
675 /* p->lastpkt_recv_time, p->next_action_time and such: */
676 for (item = G.ntp_peers; item != NULL; item = item->link) {
677 peer_t *pp = (peer_t *) item->data;
678 reset_peer_stats(pp, offset);
679 }
680 /* Globals: */
681 G.cur_time -= offset;
682 G.last_update_recv_time -= offset;
666} 683}
667 684
668 685
@@ -700,7 +717,8 @@ compare_survivor_metric(const void *aa, const void *bb)
700static int 717static int
701fit(peer_t *p, double rd) 718fit(peer_t *p, double rd)
702{ 719{
703 if (p->p_reachable_bits == 0) { 720 if ((p->reachable_bits & (p->reachable_bits-1)) == 0) {
721 /* One or zero bits in reachable_bits */
704 VERB3 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted); 722 VERB3 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted);
705 return 0; 723 return 0;
706 } 724 }
@@ -712,7 +730,7 @@ fit(peer_t *p, double rd)
712 return 0; 730 return 0;
713 } 731 }
714#endif 732#endif
715 /* rd is root_distance(p, t) */ 733 /* rd is root_distance(p) */
716 if (rd > MAXDIST + FREQ_TOLERANCE * (1 << G.poll_exp)) { 734 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); 735 VERB3 bb_error_msg("peer %s unfit for selection: root distance too high", p->p_dotted);
718 return 0; 736 return 0;
@@ -724,7 +742,7 @@ fit(peer_t *p, double rd)
724 return 1; 742 return 1;
725} 743}
726static peer_t* 744static peer_t*
727select_and_cluster(double t) 745select_and_cluster(void)
728{ 746{
729 llist_t *item; 747 llist_t *item;
730 int i, j; 748 int i, j;
@@ -742,9 +760,9 @@ select_and_cluster(double t)
742 760
743 num_points = 0; 761 num_points = 0;
744 item = G.ntp_peers; 762 item = G.ntp_peers;
745 while (item != NULL) { 763 if (G.initial_poll_complete) while (item != NULL) {
746 peer_t *p = (peer_t *) item->data; 764 peer_t *p = (peer_t *) item->data;
747 double rd = root_distance(p, t); 765 double rd = root_distance(p);
748 double offset = p->filter_offset; 766 double offset = p->filter_offset;
749 767
750 if (!fit(p, rd)) { 768 if (!fit(p, rd)) {
@@ -775,7 +793,7 @@ select_and_cluster(double t)
775 num_candidates = num_points / 3; 793 num_candidates = num_points / 3;
776 if (num_candidates == 0) { 794 if (num_candidates == 0) {
777 VERB3 bb_error_msg("no valid datapoints, no peer selected"); 795 VERB3 bb_error_msg("no valid datapoints, no peer selected");
778 return NULL; /* never happers? */ 796 return NULL;
779 } 797 }
780//TODO: sorting does not seem to be done in reference code 798//TODO: sorting does not seem to be done in reference code
781 qsort(point, num_points, sizeof(point[0]), compare_point_edge); 799 qsort(point, num_points, sizeof(point[0]), compare_point_edge);
@@ -856,7 +874,7 @@ select_and_cluster(double t)
856 p = point[i].p; 874 p = point[i].p;
857 survivor[num_survivors].p = p; 875 survivor[num_survivors].p = p;
858//TODO: save root_distance in point_t and reuse here? 876//TODO: save root_distance in point_t and reuse here?
859 survivor[num_survivors].metric = MAXDIST * p->lastpkt_stratum + root_distance(p, t); 877 survivor[num_survivors].metric = MAXDIST * p->lastpkt_stratum + root_distance(p);
860 VERB4 bb_error_msg("survivor[%d] metric:%f peer:%s", 878 VERB4 bb_error_msg("survivor[%d] metric:%f peer:%s",
861 num_survivors, survivor[num_survivors].metric, p->p_dotted); 879 num_survivors, survivor[num_survivors].metric, p->p_dotted);
862 num_survivors++; 880 num_survivors++;
@@ -952,7 +970,7 @@ select_and_cluster(double t)
952 VERB3 bb_error_msg("selected peer %s filter_offset:%f age:%f", 970 VERB3 bb_error_msg("selected peer %s filter_offset:%f age:%f",
953 survivor[0].p->p_dotted, 971 survivor[0].p->p_dotted,
954 survivor[0].p->filter_offset, 972 survivor[0].p->filter_offset,
955 t - survivor[0].p->lastpkt_recv_time 973 G.cur_time - survivor[0].p->lastpkt_recv_time
956 ); 974 );
957 return survivor[0].p; 975 return survivor[0].p;
958} 976}
@@ -981,8 +999,8 @@ set_new_values(int disc_state, double offset, double recv_time)
981#define STATE_FREQ 3 /* initial frequency */ 999#define STATE_FREQ 3 /* initial frequency */
982#define STATE_SYNC 4 /* clock synchronized (normal operation) */ 1000#define STATE_SYNC 4 /* clock synchronized (normal operation) */
983/* Return: -1: decrease poll interval, 0: leave as is, 1: increase */ 1001/* Return: -1: decrease poll interval, 0: leave as is, 1: increase */
984static int 1002static NOINLINE int
985update_local_clock(peer_t *p, double t) 1003update_local_clock(peer_t *p)
986{ 1004{
987 int rc; 1005 int rc;
988 long old_tmx_offset; 1006 long old_tmx_offset;
@@ -1037,8 +1055,6 @@ update_local_clock(peer_t *p, double t)
1037 * offset exceeds the step threshold and when it does not. 1055 * offset exceeds the step threshold and when it does not.
1038 */ 1056 */
1039 if (abs_offset > STEP_THRESHOLD) { 1057 if (abs_offset > STEP_THRESHOLD) {
1040 llist_t *item;
1041
1042 switch (G.discipline_state) { 1058 switch (G.discipline_state) {
1043 case STATE_SYNC: 1059 case STATE_SYNC:
1044 /* The first outlyer: ignore it, switch to SPIK state */ 1060 /* The first outlyer: ignore it, switch to SPIK state */
@@ -1089,10 +1105,6 @@ update_local_clock(peer_t *p, double t)
1089 G.polladj_count = 0; 1105 G.polladj_count = 0;
1090 G.poll_exp = MINPOLL; 1106 G.poll_exp = MINPOLL;
1091 G.stratum = MAXSTRAT; 1107 G.stratum = MAXSTRAT;
1092 for (item = G.ntp_peers; item != NULL; item = item->link) {
1093 peer_t *pp = (peer_t *) item->data;
1094 reset_peer_stats(pp, t, offset);
1095 }
1096 if (G.discipline_state == STATE_NSET) { 1108 if (G.discipline_state == STATE_NSET) {
1097 set_new_values(STATE_FREQ, /*offset:*/ 0, recv_time); 1109 set_new_values(STATE_FREQ, /*offset:*/ 0, recv_time);
1098 return 1; /* "ok to increase poll interval" */ 1110 return 1; /* "ok to increase poll interval" */
@@ -1101,8 +1113,9 @@ update_local_clock(peer_t *p, double t)
1101 1113
1102 } else { /* abs_offset <= STEP_THRESHOLD */ 1114 } else { /* abs_offset <= STEP_THRESHOLD */
1103 1115
1104 if (G.poll_exp < MINPOLL) { 1116 if (G.poll_exp < MINPOLL && G.initial_poll_complete) {
1105 VERB3 bb_error_msg("saw small offset %f, disabling burst mode", offset); 1117 VERB3 bb_error_msg("small offset:%f, disabling burst mode", offset);
1118 G.polladj_count = 0;
1106 G.poll_exp = MINPOLL; 1119 G.poll_exp = MINPOLL;
1107 } 1120 }
1108 1121
@@ -1128,7 +1141,7 @@ update_local_clock(peer_t *p, double t)
1128 */ 1141 */
1129 set_new_values(STATE_FREQ, offset, recv_time); 1142 set_new_values(STATE_FREQ, offset, recv_time);
1130 VERB3 bb_error_msg("transitioning to FREQ, datapoint ignored"); 1143 VERB3 bb_error_msg("transitioning to FREQ, datapoint ignored");
1131 return -1; /* "decrease poll interval" */ 1144 return 0; /* "leave poll interval as is" */
1132 1145
1133#if 0 /* this is dead code for now */ 1146#if 0 /* this is dead code for now */
1134 case STATE_FSET: 1147 case STATE_FSET:
@@ -1180,12 +1193,12 @@ update_local_clock(peer_t *p, double t)
1180 G.stratum = p->lastpkt_stratum + 1; 1193 G.stratum = p->lastpkt_stratum + 1;
1181 } 1194 }
1182 1195
1183 G.reftime = t; 1196 G.reftime = G.cur_time;
1184 G.ntp_status = p->lastpkt_status; 1197 G.ntp_status = p->lastpkt_status;
1185 G.refid = p->lastpkt_refid; 1198 G.refid = p->lastpkt_refid;
1186 G.rootdelay = p->lastpkt_rootdelay + p->lastpkt_delay; 1199 G.rootdelay = p->lastpkt_rootdelay + p->lastpkt_delay;
1187 dtemp = p->filter_jitter; // SQRT(SQUARE(p->filter_jitter) + SQUARE(s.jitter)); 1200 dtemp = p->filter_jitter; // SQRT(SQUARE(p->filter_jitter) + SQUARE(s.jitter));
1188 dtemp += MAXD(p->filter_dispersion + FREQ_TOLERANCE * (t - p->lastpkt_recv_time) + abs_offset, MINDISP); 1201 dtemp += MAXD(p->filter_dispersion + FREQ_TOLERANCE * (G.cur_time - p->lastpkt_recv_time) + abs_offset, MINDISP);
1189 G.rootdisp = p->lastpkt_rootdisp + dtemp; 1202 G.rootdisp = p->lastpkt_rootdisp + dtemp;
1190 VERB3 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted); 1203 VERB3 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted);
1191 1204
@@ -1318,19 +1331,20 @@ retry_interval(void)
1318 return interval; 1331 return interval;
1319} 1332}
1320static unsigned 1333static unsigned
1321poll_interval(int exponent) /* exp is always -1 or 0 */ 1334poll_interval(int exponent)
1322{ 1335{
1323 /* Want to send next packet at (1 << G.poll_exp) + small random value */ 1336 /* Want to send next packet at (1 << G.poll_exp) + small random value */
1324 unsigned interval, r; 1337 unsigned interval, r;
1325 exponent += G.poll_exp; /* G.poll_exp is always > 0 */ 1338 exponent = G.poll_exp + exponent;
1326 /* never true: if (exp < 0) exp = 0; */ 1339 if (exponent < 0)
1340 exponent = 0;
1327 interval = 1 << exponent; 1341 interval = 1 << exponent;
1328 r = random(); 1342 r = random();
1329 interval += ((r & (interval-1)) >> 4) + ((r >> 8) & 1); /* + 1/16 of interval, max */ 1343 interval += ((r & (interval-1)) >> 4) + ((r >> 8) & 1); /* + 1/16 of interval, max */
1330 VERB3 bb_error_msg("chose poll interval:%u (poll_exp:%d exp:%d)", interval, G.poll_exp, exponent); 1344 VERB3 bb_error_msg("chose poll interval:%u (poll_exp:%d exp:%d)", interval, G.poll_exp, exponent);
1331 return interval; 1345 return interval;
1332} 1346}
1333static void 1347static NOINLINE void
1334recv_and_process_peer_pkt(peer_t *p) 1348recv_and_process_peer_pkt(peer_t *p)
1335{ 1349{
1336 int rc; 1350 int rc;
@@ -1410,12 +1424,12 @@ recv_and_process_peer_pkt(peer_t *p)
1410 T1 = p->p_xmttime; 1424 T1 = p->p_xmttime;
1411 T2 = lfp_to_d(msg.m_rectime); 1425 T2 = lfp_to_d(msg.m_rectime);
1412 T3 = lfp_to_d(msg.m_xmttime); 1426 T3 = lfp_to_d(msg.m_xmttime);
1413 T4 = gettime1900d(); 1427 T4 = G.cur_time;
1414 1428
1415 p->lastpkt_recv_time = T4; 1429 p->lastpkt_recv_time = T4;
1416 1430
1417 VERB5 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time); 1431 VERB5 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
1418 p->datapoint_idx = p->p_reachable_bits ? (p->datapoint_idx + 1) % NUM_DATAPOINTS : 0; 1432 p->datapoint_idx = p->reachable_bits ? (p->datapoint_idx + 1) % NUM_DATAPOINTS : 0;
1419 datapoint = &p->filter_datapoint[p->datapoint_idx]; 1433 datapoint = &p->filter_datapoint[p->datapoint_idx];
1420 datapoint->d_recv_time = T4; 1434 datapoint->d_recv_time = T4;
1421 datapoint->d_offset = ((T2 - T1) + (T3 - T4)) / 2; 1435 datapoint->d_offset = ((T2 - T1) + (T3 - T4)) / 2;
@@ -1429,7 +1443,7 @@ recv_and_process_peer_pkt(peer_t *p)
1429 if (p->lastpkt_delay < G_precision_sec) 1443 if (p->lastpkt_delay < G_precision_sec)
1430 p->lastpkt_delay = G_precision_sec; 1444 p->lastpkt_delay = G_precision_sec;
1431 datapoint->d_dispersion = LOG2D(msg.m_precision_exp) + G_precision_sec; 1445 datapoint->d_dispersion = LOG2D(msg.m_precision_exp) + G_precision_sec;
1432 if (!p->p_reachable_bits) { 1446 if (!p->reachable_bits) {
1433 /* 1st datapoint ever - replicate offset in every element */ 1447 /* 1st datapoint ever - replicate offset in every element */
1434 int i; 1448 int i;
1435 for (i = 1; i < NUM_DATAPOINTS; i++) { 1449 for (i = 1; i < NUM_DATAPOINTS; i++) {
@@ -1437,20 +1451,20 @@ recv_and_process_peer_pkt(peer_t *p)
1437 } 1451 }
1438 } 1452 }
1439 1453
1440 p->p_reachable_bits |= 1; 1454 p->reachable_bits |= 1;
1441 VERB1 { 1455 VERB1 {
1442 bb_error_msg("reply from %s: reach 0x%02x offset %f delay %f", 1456 bb_error_msg("reply from %s: reach 0x%02x offset %f delay %f",
1443 p->p_dotted, 1457 p->p_dotted,
1444 p->p_reachable_bits, 1458 p->reachable_bits,
1445 datapoint->d_offset, p->lastpkt_delay); 1459 datapoint->d_offset, p->lastpkt_delay);
1446 } 1460 }
1447 1461
1448 /* Muck with statictics and update the clock */ 1462 /* Muck with statictics and update the clock */
1449 filter_datapoints(p, T4); 1463 filter_datapoints(p);
1450 q = select_and_cluster(T4); 1464 q = select_and_cluster();
1451 rc = -1; 1465 rc = -1;
1452 if (q) 1466 if (q)
1453 rc = update_local_clock(q, T4); 1467 rc = update_local_clock(q);
1454 1468
1455 if (rc != 0) { 1469 if (rc != 0) {
1456 /* Adjust the poll interval by comparing the current offset 1470 /* Adjust the poll interval by comparing the current offset
@@ -1524,12 +1538,11 @@ recv_and_process_peer_pkt(peer_t *p)
1524} 1538}
1525 1539
1526#if ENABLE_FEATURE_NTPD_SERVER 1540#if ENABLE_FEATURE_NTPD_SERVER
1527static void 1541static NOINLINE void
1528recv_and_process_client_pkt(void /*int fd*/) 1542recv_and_process_client_pkt(void /*int fd*/)
1529{ 1543{
1530 ssize_t size; 1544 ssize_t size;
1531 uint8_t version; 1545 uint8_t version;
1532 double rectime;
1533 len_and_sockaddr *to; 1546 len_and_sockaddr *to;
1534 struct sockaddr *from; 1547 struct sockaddr *from;
1535 msg_t msg; 1548 msg_t msg;
@@ -1565,8 +1578,9 @@ recv_and_process_client_pkt(void /*int fd*/)
1565 msg.m_stratum = G.stratum; 1578 msg.m_stratum = G.stratum;
1566 msg.m_ppoll = G.poll_exp; 1579 msg.m_ppoll = G.poll_exp;
1567 msg.m_precision_exp = G_precision_exp; 1580 msg.m_precision_exp = G_precision_exp;
1568 rectime = gettime1900d(); 1581 /* this time was obtained between poll() and recv() */
1569 msg.m_xmttime = msg.m_rectime = d_to_lfp(rectime); 1582 msg.m_rectime = d_to_lfp(G.cur_time);
1583 msg.m_xmttime = d_to_lfp(gettime1900d()); /* this instant */
1570 msg.m_reftime = d_to_lfp(G.reftime); 1584 msg.m_reftime = d_to_lfp(G.reftime);
1571 msg.m_orgtime = query_xmttime; 1585 msg.m_orgtime = query_xmttime;
1572 msg.m_rootdelay = d_to_sfp(G.rootdelay); 1586 msg.m_rootdelay = d_to_sfp(G.rootdelay);
@@ -1686,33 +1700,10 @@ static NOINLINE void ntp_init(char **argv)
1686 bb_error_msg_and_die(bb_msg_you_must_be_root); 1700 bb_error_msg_and_die(bb_msg_you_must_be_root);
1687 1701
1688 /* Set some globals */ 1702 /* Set some globals */
1689#if 0
1690 /* With constant b = 100, G.precision_exp is also constant -6.
1691 * Uncomment this to verify.
1692 */
1693 {
1694 int prec = 0;
1695 int b;
1696# if 0
1697 struct timespec tp;
1698 /* We can use sys_clock_getres but assuming 10ms tick should be fine */
1699 clock_getres(CLOCK_REALTIME, &tp);
1700 tp.tv_sec = 0;
1701 tp.tv_nsec = 10000000;
1702 b = 1000000000 / tp.tv_nsec; /* convert to Hz */
1703# else
1704 b = 100; /* b = 1000000000/10000000 = 100 */
1705# endif
1706 while (b > 1)
1707 prec--, b >>= 1;
1708 /*G.precision_exp = prec;*/
1709 /*G.precision_sec = (1.0 / (1 << (- prec)));*/
1710 bb_error_msg("G.precision_exp:%d sec:%f", prec, G_precision_sec); /* -6 */
1711 }
1712#endif
1713 G.stratum = MAXSTRAT; 1703 G.stratum = MAXSTRAT;
1714 G.poll_exp = 1; /* should use MINPOLL, but 1 speeds up initial sync */ 1704 if (BURSTPOLL != 0)
1715 G.reftime = G.last_update_recv_time = gettime1900d(); 1705 G.poll_exp = BURSTPOLL; /* speeds up initial sync */
1706 G.reftime = G.last_update_recv_time = gettime1900d(); /* sets G.cur_time too */
1716 1707
1717 /* Parse options */ 1708 /* Parse options */
1718 peers = NULL; 1709 peers = NULL;
@@ -1752,61 +1743,66 @@ static NOINLINE void ntp_init(char **argv)
1752int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE; 1743int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE;
1753int ntpd_main(int argc UNUSED_PARAM, char **argv) 1744int ntpd_main(int argc UNUSED_PARAM, char **argv)
1754{ 1745{
1755 struct globals g; 1746#undef G
1747 struct globals G;
1756 struct pollfd *pfd; 1748 struct pollfd *pfd;
1757 peer_t **idx2peer; 1749 peer_t **idx2peer;
1750 unsigned cnt;
1758 1751
1759 memset(&g, 0, sizeof(g)); 1752 memset(&G, 0, sizeof(G));
1760 SET_PTR_TO_GLOBALS(&g); 1753 SET_PTR_TO_GLOBALS(&G);
1761 1754
1762 ntp_init(argv); 1755 ntp_init(argv);
1763 1756
1764 { 1757 /* If ENABLE_FEATURE_NTPD_SERVER, + 1 for listen_fd: */
1765 /* if ENABLE_FEATURE_NTPD_SERVER, + 1 for listen_fd: */ 1758 cnt = G.peer_cnt + ENABLE_FEATURE_NTPD_SERVER;
1766 unsigned cnt = g.peer_cnt + ENABLE_FEATURE_NTPD_SERVER; 1759 idx2peer = xzalloc(sizeof(idx2peer[0]) * cnt);
1767 idx2peer = xzalloc(sizeof(idx2peer[0]) * cnt); 1760 pfd = xzalloc(sizeof(pfd[0]) * cnt);
1768 pfd = xzalloc(sizeof(pfd[0]) * cnt); 1761
1769 } 1762 /* Countdown: we never sync before we sent 5 packets to each peer
1763 * NB: if some peer is not responding, we may end up sending
1764 * fewer packets to it and more to other peers.
1765 * NB2: sync usually happens using 5-1=4 packets, since last reply
1766 * does not come back instantaneously.
1767 */
1768 cnt = G.peer_cnt * 5;
1770 1769
1771 while (!bb_got_signal) { 1770 while (!bb_got_signal) {
1772 llist_t *item; 1771 llist_t *item;
1773 unsigned i, j; 1772 unsigned i, j;
1774 unsigned sent_cnt, trial_cnt;
1775 int nfds, timeout; 1773 int nfds, timeout;
1776 time_t cur_time, nextaction; 1774 double nextaction;
1777 1775
1778 /* Nothing between here and poll() blocks for any significant time */ 1776 /* Nothing between here and poll() blocks for any significant time */
1779 1777
1780 cur_time = time(NULL); 1778 nextaction = G.cur_time + 3600;
1781 nextaction = cur_time + 3600;
1782 1779
1783 i = 0; 1780 i = 0;
1784#if ENABLE_FEATURE_NTPD_SERVER 1781#if ENABLE_FEATURE_NTPD_SERVER
1785 if (g.listen_fd != -1) { 1782 if (G.listen_fd != -1) {
1786 pfd[0].fd = g.listen_fd; 1783 pfd[0].fd = G.listen_fd;
1787 pfd[0].events = POLLIN; 1784 pfd[0].events = POLLIN;
1788 i++; 1785 i++;
1789 } 1786 }
1790#endif 1787#endif
1791 /* Pass over peer list, send requests, time out on receives */ 1788 /* Pass over peer list, send requests, time out on receives */
1792 sent_cnt = trial_cnt = 0; 1789 for (item = G.ntp_peers; item != NULL; item = item->link) {
1793 for (item = g.ntp_peers; item != NULL; item = item->link) {
1794 peer_t *p = (peer_t *) item->data; 1790 peer_t *p = (peer_t *) item->data;
1795 1791
1796 /* Overflow-safe "if (p->next_action_time <= cur_time) ..." */ 1792 if (p->next_action_time <= G.cur_time) {
1797 if ((int)(cur_time - p->next_action_time) >= 0) {
1798 if (p->p_fd == -1) { 1793 if (p->p_fd == -1) {
1799 /* Time to send new req */ 1794 /* Time to send new req */
1800 trial_cnt++; 1795 if (--cnt == 0) {
1801 if (send_query_to_peer(p) == 0) 1796 G.initial_poll_complete = 1;
1802 sent_cnt++; 1797 }
1798 send_query_to_peer(p);
1803 } else { 1799 } else {
1804 /* Timed out waiting for reply */ 1800 /* Timed out waiting for reply */
1805 close(p->p_fd); 1801 close(p->p_fd);
1806 p->p_fd = -1; 1802 p->p_fd = -1;
1807 timeout = poll_interval(-1); /* try a bit faster */ 1803 timeout = poll_interval(-2); /* -2: try a bit sooner */
1808 bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us", 1804 bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us",
1809 p->p_dotted, p->p_reachable_bits, timeout); 1805 p->p_dotted, p->reachable_bits, timeout);
1810 set_next(p, timeout); 1806 set_next(p, timeout);
1811 } 1807 }
1812 } 1808 }
@@ -1823,23 +1819,26 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
1823 } 1819 }
1824 } 1820 }
1825 1821
1826 timeout = nextaction - cur_time; 1822 timeout = nextaction - G.cur_time;
1827 if (timeout < 1) 1823 if (timeout < 0)
1828 timeout = 1; 1824 timeout = 0;
1825 timeout++; /* (nextaction - G.cur_time) rounds down, compensating */
1829 1826
1830 /* Here we may block */ 1827 /* Here we may block */
1831 VERB2 bb_error_msg("poll %us, sockets:%u", timeout, i); 1828 VERB2 bb_error_msg("poll %us, sockets:%u", timeout, i);
1832 nfds = poll(pfd, i, timeout * 1000); 1829 nfds = poll(pfd, i, timeout * 1000);
1830 gettime1900d(); /* sets G.cur_time */
1833 if (nfds <= 0) 1831 if (nfds <= 0)
1834 continue; 1832 continue;
1835 1833
1836 /* Process any received packets */ 1834 /* Process any received packets */
1837 j = 0; 1835 j = 0;
1838#if ENABLE_FEATURE_NTPD_SERVER 1836#if ENABLE_FEATURE_NTPD_SERVER
1839 if (g.listen_fd != -1) { 1837 if (G.listen_fd != -1) {
1840 if (pfd[0].revents /* & (POLLIN|POLLERR)*/) { 1838 if (pfd[0].revents /* & (POLLIN|POLLERR)*/) {
1841 nfds--; 1839 nfds--;
1842 recv_and_process_client_pkt(/*g.listen_fd*/); 1840 recv_and_process_client_pkt(/*G.listen_fd*/);
1841 gettime1900d(); /* sets G.cur_time */
1843 } 1842 }
1844 j = 1; 1843 j = 1;
1845 } 1844 }
@@ -1848,6 +1847,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
1848 if (pfd[j].revents /* & (POLLIN|POLLERR)*/) { 1847 if (pfd[j].revents /* & (POLLIN|POLLERR)*/) {
1849 nfds--; 1848 nfds--;
1850 recv_and_process_peer_pkt(idx2peer[j]); 1849 recv_and_process_peer_pkt(idx2peer[j]);
1850 gettime1900d(); /* sets G.cur_time */
1851 } 1851 }
1852 } 1852 }
1853 } /* while (!bb_got_signal) */ 1853 } /* while (!bb_got_signal) */