aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-01-02 00:36:43 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-01-02 00:36:43 +0100
commitd9109e3b48d2eb2eebcc433bfa4d04a653a93d9b (patch)
tree11477a2190f04831338585126984ca6fafb9de47
parenta9aaeda0e9714eec74894734b30b6f5a45c97a48 (diff)
downloadbusybox-w32-d9109e3b48d2eb2eebcc433bfa4d04a653a93d9b.tar.gz
busybox-w32-d9109e3b48d2eb2eebcc433bfa4d04a653a93d9b.tar.bz2
busybox-w32-d9109e3b48d2eb2eebcc433bfa4d04a653a93d9b.zip
ntpd: improve frequency filtering
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/ntpd.c64
1 files changed, 43 insertions, 21 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 5431b7499..5cad738c6 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -390,8 +390,13 @@ static void
390filter_datapoints(peer_t *p, double t) 390filter_datapoints(peer_t *p, double t)
391{ 391{
392 int i, idx; 392 int i, idx;
393 int got_newest;
393 double minoff, maxoff, wavg, sum, w; 394 double minoff, maxoff, wavg, sum, w;
394 double x = x; 395 double x = x; /* for compiler */
396 double oldest_off = oldest_off;
397 double oldest_age = oldest_age;
398 double newest_off = newest_off;
399 double newest_age = newest_age;
395 400
396 minoff = maxoff = p->filter_datapoint[0].d_offset; 401 minoff = maxoff = p->filter_datapoint[0].d_offset;
397 for (i = 1; i < NUM_DATAPOINTS; i++) { 402 for (i = 1; i < NUM_DATAPOINTS; i++) {
@@ -416,6 +421,7 @@ filter_datapoints(peer_t *p, double t)
416 // / (i+1) 421 // / (i+1)
417 // --- 2 422 // --- 2
418 // i=0 423 // i=0
424 got_newest = 0;
419 sum = 0; 425 sum = 0;
420 for (i = 0; i < NUM_DATAPOINTS; i++) { 426 for (i = 0; i < NUM_DATAPOINTS; i++) {
421 VERB4 { 427 VERB4 {
@@ -437,23 +443,36 @@ filter_datapoints(peer_t *p, double t)
437 if (maxoff == p->filter_datapoint[idx].d_offset) { 443 if (maxoff == p->filter_datapoint[idx].d_offset) {
438 maxoff += 1; 444 maxoff += 1;
439 } else { 445 } else {
440 x = p->filter_datapoint[idx].d_offset * w; 446 oldest_off = p->filter_datapoint[idx].d_offset;
447 oldest_age = t - p->filter_datapoint[idx].d_recv_time;
448 if (!got_newest) {
449 got_newest = 1;
450 newest_off = oldest_off;
451 newest_age = oldest_age;
452 }
453 x = oldest_off * w;
441 wavg += x; 454 wavg += x;
442 w /= 2; 455 w /= 2;
443 } 456 }
444 457
445 idx = (idx - 1) & (NUM_DATAPOINTS - 1); 458 idx = (idx - 1) & (NUM_DATAPOINTS - 1);
446 } 459 }
460 p->filter_dispersion = sum;
447 wavg += x; /* add another older6/64 to form older6/32 */ 461 wavg += x; /* add another older6/64 to form older6/32 */
462 /* Fix systematic underestimation with large poll intervals.
463 * Imagine that we still have a bit of uncorrected drift,
464 * and poll interval is big (say, 100 sec). Offsets form a progression:
465 * 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 - 0.7 is most recent.
466 * The algorithm above drops 0.0 and 0.7 as outliers,
467 * and then we have this estimation, ~25% off from 0.7:
468 * 0.1/32 + 0.2/32 + 0.3/16 + 0.4/8 + 0.5/4 + 0.6/2 = 0.503125
469 */
470 x = newest_age / (oldest_age - newest_age); /* in above example, 100 / (600 - 100) */
471 if (x < 1) {
472 x = (newest_off - oldest_off) * x; /* 0.5 * 100/500 = 0.1 */
473 wavg += x;
474 }
448 p->filter_offset = wavg; 475 p->filter_offset = wavg;
449 p->filter_dispersion = sum;
450//TODO: fix systematic underestimation with large poll intervals.
451// Imagine that we still have a bit of uncorrected drift,
452// and poll interval is big. Offsets form a progression:
453// 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7, 0.7 is most recent.
454// The algorithm above drops 0.0 and 0.7 as outliers,
455// and then we have this estimation, ~25% off from 0.7:
456// 0.1/32 + 0.2/32 + 0.3/16 + 0.4/8 + 0.5/4 + 0.6/2 = 0.503125
457 476
458 // +----- -----+ ^ 1/2 477 // +----- -----+ ^ 1/2
459 // | n-1 | 478 // | n-1 |
@@ -472,8 +491,10 @@ filter_datapoints(peer_t *p, double t)
472 sum = SQRT(sum) / NUM_DATAPOINTS; 491 sum = SQRT(sum) / NUM_DATAPOINTS;
473 p->filter_jitter = sum > G_precision_sec ? sum : G_precision_sec; 492 p->filter_jitter = sum > G_precision_sec ? sum : G_precision_sec;
474 493
475 VERB3 bb_error_msg("filter offset:%f disp:%f jitter:%f", 494 VERB3 bb_error_msg("filter offset:%f(corr:%e) disp:%f jitter:%f",
476 p->filter_offset, p->filter_dispersion, p->filter_jitter); 495 p->filter_offset, x,
496 p->filter_dispersion,
497 p->filter_jitter);
477 498
478} 499}
479 500
@@ -948,7 +969,7 @@ set_new_values(int disc_state, double offset, double recv_time)
948 * of the last clock filter sample, which must be earlier than 969 * of the last clock filter sample, which must be earlier than
949 * the current time. 970 * the current time.
950 */ 971 */
951 VERB3 bb_error_msg("disc_state=%d last_update_offset=%f last_update_recv_time=%f", 972 VERB3 bb_error_msg("disc_state=%d last update offset=%f recv_time=%f",
952 disc_state, offset, recv_time); 973 disc_state, offset, recv_time);
953 G.discipline_state = disc_state; 974 G.discipline_state = disc_state;
954 G.last_update_offset = offset; 975 G.last_update_offset = offset;
@@ -1227,26 +1248,27 @@ update_local_clock(peer_t *p, double t)
1227 tmx.constant = G.poll_exp - 4; 1248 tmx.constant = G.poll_exp - 4;
1228 //tmx.esterror = (u_int32)(clock_jitter * 1e6); 1249 //tmx.esterror = (u_int32)(clock_jitter * 1e6);
1229 //tmx.maxerror = (u_int32)((sys_rootdelay / 2 + sys_rootdisp) * 1e6); 1250 //tmx.maxerror = (u_int32)((sys_rootdelay / 2 + sys_rootdisp) * 1e6);
1230 VERB3 bb_error_msg("b adjtimex freq:%ld offset:%ld constant:%ld status:0x%x",
1231 tmx.freq, tmx.offset, tmx.constant, tmx.status);
1232 rc = adjtimex(&tmx); 1251 rc = adjtimex(&tmx);
1233 if (rc < 0) 1252 if (rc < 0)
1234 bb_perror_msg_and_die("adjtimex"); 1253 bb_perror_msg_and_die("adjtimex");
1235 if (G.kernel_freq_drift != tmx.freq / 65536) { 1254 /* NB: here kernel returns constant == G.poll_exp, not == G.poll_exp - 4.
1236 G.kernel_freq_drift = tmx.freq / 65536; 1255 * Not sure why. Perhaps it is normal.
1237 VERB2 bb_error_msg("kernel clock drift: %ld ppm", G.kernel_freq_drift); 1256 */
1238 } 1257 VERB3 bb_error_msg("adjtimex:%d freq:%ld offset:%ld constant:%ld status:0x%x",
1239 VERB3 {
1240 bb_error_msg("adjtimex:%d freq:%ld offset:%ld constant:%ld status:0x%x",
1241 rc, tmx.freq, tmx.offset, tmx.constant, tmx.status); 1258 rc, tmx.freq, tmx.offset, tmx.constant, tmx.status);
1242#if 0 1259#if 0
1260 VERB3 {
1243 /* always gives the same output as above msg */ 1261 /* always gives the same output as above msg */
1244 memset(&tmx, 0, sizeof(tmx)); 1262 memset(&tmx, 0, sizeof(tmx));
1245 if (adjtimex(&tmx) < 0) 1263 if (adjtimex(&tmx) < 0)
1246 bb_perror_msg_and_die("adjtimex"); 1264 bb_perror_msg_and_die("adjtimex");
1247 VERB3 bb_error_msg("c adjtimex freq:%ld offset:%ld constant:%ld status:0x%x", 1265 VERB3 bb_error_msg("c adjtimex freq:%ld offset:%ld constant:%ld status:0x%x",
1248 tmx.freq, tmx.offset, tmx.constant, tmx.status); 1266 tmx.freq, tmx.offset, tmx.constant, tmx.status);
1267 }
1249#endif 1268#endif
1269 if (G.kernel_freq_drift != tmx.freq / 65536) {
1270 G.kernel_freq_drift = tmx.freq / 65536;
1271 VERB2 bb_error_msg("kernel clock drift: %ld ppm", G.kernel_freq_drift);
1250 } 1272 }
1251// #define STA_MODE 0x4000 /* mode (0 = PLL, 1 = FLL) (ro) */ - ? 1273// #define STA_MODE 0x4000 /* mode (0 = PLL, 1 = FLL) (ro) */ - ?
1252// it appeared after a while: 1274// it appeared after a while: