diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-02 00:36:43 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-02 00:36:43 +0100 |
commit | d9109e3b48d2eb2eebcc433bfa4d04a653a93d9b (patch) | |
tree | 11477a2190f04831338585126984ca6fafb9de47 | |
parent | a9aaeda0e9714eec74894734b30b6f5a45c97a48 (diff) | |
download | busybox-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.c | 64 |
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 | |||
390 | filter_datapoints(peer_t *p, double t) | 390 | filter_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: |