aboutsummaryrefslogtreecommitdiff
path: root/networking/ntpd.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-01-17 02:51:33 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-01-17 02:51:33 +0100
commit9b20adca4b2b59c791b4b5579857e4f028a969ed (patch)
treeb77738b270eb05f845213299a517929dc93b6b9f /networking/ntpd.c
parent5b9a910749176cabcd6e822ca46af66a9947d032 (diff)
downloadbusybox-w32-9b20adca4b2b59c791b4b5579857e4f028a969ed.tar.gz
busybox-w32-9b20adca4b2b59c791b4b5579857e4f028a969ed.tar.bz2
busybox-w32-9b20adca4b2b59c791b4b5579857e4f028a969ed.zip
ntpd: add anti-clock-hopping code
function old new delta select_and_cluster 837 950 +113 update_local_clock 759 767 +8 root_distance 61 - -61 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/ntpd.c')
-rw-r--r--networking/ntpd.c78
1 files changed, 61 insertions, 17 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
index b2cd0a3c0..aca79c95a 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -306,13 +306,15 @@ struct globals {
306 uint8_t poll_exp; // s.poll 306 uint8_t poll_exp; // s.poll
307 int polladj_count; // c.count 307 int polladj_count; // c.count
308 long kernel_freq_drift; 308 long kernel_freq_drift;
309 peer_t *last_update_peer;
309 double last_update_offset; // c.last 310 double last_update_offset; // c.last
310 double last_update_recv_time; // s.t 311 double last_update_recv_time; // s.t
311 double discipline_jitter; // c.jitter 312 double discipline_jitter; // c.jitter
312//TODO: add s.jitter - grep for it here and see clock_combine() in doc 313 //double cluster_offset; // s.offset
314 //double cluster_jitter; // s.jitter
313#if !USING_KERNEL_PLL_LOOP 315#if !USING_KERNEL_PLL_LOOP
314 double discipline_freq_drift; // c.freq 316 double discipline_freq_drift; // c.freq
315//TODO: conditionally calculate wander? it's used only for logging 317 /* Maybe conditionally calculate wander? it's used only for logging */
316 double discipline_wander; // c.wander 318 double discipline_wander; // c.wander
317#endif 319#endif
318}; 320};
@@ -821,6 +823,7 @@ typedef struct {
821 peer_t *p; 823 peer_t *p;
822 int type; 824 int type;
823 double edge; 825 double edge;
826 double opt_rd; /* optimization */
824} point_t; 827} point_t;
825static int 828static int
826compare_point_edge(const void *aa, const void *bb) 829compare_point_edge(const void *aa, const void *bb)
@@ -876,6 +879,7 @@ fit(peer_t *p, double rd)
876static peer_t* 879static peer_t*
877select_and_cluster(void) 880select_and_cluster(void)
878{ 881{
882 peer_t *p;
879 llist_t *item; 883 llist_t *item;
880 int i, j; 884 int i, j;
881 int size = 3 * G.peer_cnt; 885 int size = 3 * G.peer_cnt;
@@ -893,10 +897,11 @@ select_and_cluster(void)
893 num_points = 0; 897 num_points = 0;
894 item = G.ntp_peers; 898 item = G.ntp_peers;
895 if (G.initial_poll_complete) while (item != NULL) { 899 if (G.initial_poll_complete) while (item != NULL) {
896 peer_t *p = (peer_t *) item->data; 900 double rd, offset;
897 double rd = root_distance(p);
898 double offset = p->filter_offset;
899 901
902 p = (peer_t *) item->data;
903 rd = root_distance(p);
904 offset = p->filter_offset;
900 if (!fit(p, rd)) { 905 if (!fit(p, rd)) {
901 item = item->link; 906 item = item->link;
902 continue; 907 continue;
@@ -911,14 +916,17 @@ select_and_cluster(void)
911 point[num_points].p = p; 916 point[num_points].p = p;
912 point[num_points].type = -1; 917 point[num_points].type = -1;
913 point[num_points].edge = offset - rd; 918 point[num_points].edge = offset - rd;
919 point[num_points].opt_rd = rd;
914 num_points++; 920 num_points++;
915 point[num_points].p = p; 921 point[num_points].p = p;
916 point[num_points].type = 0; 922 point[num_points].type = 0;
917 point[num_points].edge = offset; 923 point[num_points].edge = offset;
924 point[num_points].opt_rd = rd;
918 num_points++; 925 num_points++;
919 point[num_points].p = p; 926 point[num_points].p = p;
920 point[num_points].type = 1; 927 point[num_points].type = 1;
921 point[num_points].edge = offset + rd; 928 point[num_points].edge = offset + rd;
929 point[num_points].opt_rd = rd;
922 num_points++; 930 num_points++;
923 item = item->link; 931 item = item->link;
924 } 932 }
@@ -999,14 +1007,12 @@ select_and_cluster(void)
999 */ 1007 */
1000 num_survivors = 0; 1008 num_survivors = 0;
1001 for (i = 0; i < num_points; i++) { 1009 for (i = 0; i < num_points; i++) {
1002 peer_t *p;
1003
1004 if (point[i].edge < low || point[i].edge > high) 1010 if (point[i].edge < low || point[i].edge > high)
1005 continue; 1011 continue;
1006 p = point[i].p; 1012 p = point[i].p;
1007 survivor[num_survivors].p = p; 1013 survivor[num_survivors].p = p;
1008//TODO: save root_distance in point_t and reuse here? 1014 /* x.opt_rd == root_distance(p); */
1009 survivor[num_survivors].metric = MAXDIST * p->lastpkt_stratum + root_distance(p); 1015 survivor[num_survivors].metric = MAXDIST * p->lastpkt_stratum + point[i].opt_rd;
1010 VERB4 bb_error_msg("survivor[%d] metric:%f peer:%s", 1016 VERB4 bb_error_msg("survivor[%d] metric:%f peer:%s",
1011 num_survivors, survivor[num_survivors].metric, p->p_dotted); 1017 num_survivors, survivor[num_survivors].metric, p->p_dotted);
1012 num_survivors++; 1018 num_survivors++;
@@ -1050,8 +1056,8 @@ select_and_cluster(void)
1050 */ 1056 */
1051 for (i = 0; i < num_survivors; i++) { 1057 for (i = 0; i < num_survivors; i++) {
1052 double selection_jitter_sq; 1058 double selection_jitter_sq;
1053 peer_t *p = survivor[i].p;
1054 1059
1060 p = survivor[i].p;
1055 if (i == 0 || p->filter_jitter < min_jitter) 1061 if (i == 0 || p->filter_jitter < min_jitter)
1056 min_jitter = p->filter_jitter; 1062 min_jitter = p->filter_jitter;
1057 1063
@@ -1093,18 +1099,54 @@ select_and_cluster(void)
1093 } 1099 }
1094 } 1100 }
1095 1101
1102 if (0) {
1103 /* Combine the offsets of the clustering algorithm survivors
1104 * using a weighted average with weight determined by the root
1105 * distance. Compute the selection jitter as the weighted RMS
1106 * difference between the first survivor and the remaining
1107 * survivors. In some cases the inherent clock jitter can be
1108 * reduced by not using this algorithm, especially when frequent
1109 * clockhopping is involved. bbox: thus we don't do it.
1110 */
1111 double x, y, z, w;
1112 y = z = w = 0;
1113 for (i = 0; i < num_survivors; i++) {
1114 p = survivor[i].p;
1115 x = root_distance(p);
1116 y += 1 / x;
1117 z += p->filter_offset / x;
1118 w += SQUARE(p->filter_offset - survivor[0].p->filter_offset) / x;
1119 }
1120 //G.cluster_offset = z / y;
1121 //G.cluster_jitter = SQRT(w / y);
1122 }
1123
1096 /* Pick the best clock. If the old system peer is on the list 1124 /* Pick the best clock. If the old system peer is on the list
1097 * and at the same stratum as the first survivor on the list, 1125 * and at the same stratum as the first survivor on the list,
1098 * then don't do a clock hop. Otherwise, select the first 1126 * then don't do a clock hop. Otherwise, select the first
1099 * survivor on the list as the new system peer. 1127 * survivor on the list as the new system peer.
1100 */ 1128 */
1101//TODO - see clock_combine() 1129 p = survivor[0].p;
1130 if (G.last_update_peer
1131 && G.last_update_peer->lastpkt_stratum <= p->lastpkt_stratum
1132 ) {
1133 /* Starting from 1 is ok here */
1134 for (i = 1; i < num_survivors; i++) {
1135 if (G.last_update_peer == survivor[i].p) {
1136 VERB4 bb_error_msg("keeping old synced peer");
1137 p = G.last_update_peer;
1138 goto keep_old;
1139 }
1140 }
1141 }
1142 G.last_update_peer = p;
1143 keep_old:
1102 VERB3 bb_error_msg("selected peer %s filter_offset:%f age:%f", 1144 VERB3 bb_error_msg("selected peer %s filter_offset:%f age:%f",
1103 survivor[0].p->p_dotted, 1145 p->p_dotted,
1104 survivor[0].p->filter_offset, 1146 p->filter_offset,
1105 G.cur_time - survivor[0].p->lastpkt_recv_time 1147 G.cur_time - p->lastpkt_recv_time
1106 ); 1148 );
1107 return survivor[0].p; 1149 return p;
1108} 1150}
1109 1151
1110 1152
@@ -1131,6 +1173,7 @@ update_local_clock(peer_t *p)
1131 int rc; 1173 int rc;
1132 long old_tmx_offset; 1174 long old_tmx_offset;
1133 struct timex tmx; 1175 struct timex tmx;
1176 /* Note: can use G.cluster_offset instead: */
1134 double offset = p->filter_offset; 1177 double offset = p->filter_offset;
1135 double recv_time = p->lastpkt_recv_time; 1178 double recv_time = p->lastpkt_recv_time;
1136 double abs_offset; 1179 double abs_offset;
@@ -1343,7 +1386,7 @@ update_local_clock(peer_t *p)
1343 G.ntp_status = p->lastpkt_status; 1386 G.ntp_status = p->lastpkt_status;
1344 G.refid = p->lastpkt_refid; 1387 G.refid = p->lastpkt_refid;
1345 G.rootdelay = p->lastpkt_rootdelay + p->lastpkt_delay; 1388 G.rootdelay = p->lastpkt_rootdelay + p->lastpkt_delay;
1346 dtemp = p->filter_jitter; // SQRT(SQUARE(p->filter_jitter) + SQUARE(s.jitter)); 1389 dtemp = p->filter_jitter; // SQRT(SQUARE(p->filter_jitter) + SQUARE(G.cluster_jitter));
1347 dtemp += MAXD(p->filter_dispersion + FREQ_TOLERANCE * (G.cur_time - p->lastpkt_recv_time) + abs_offset, MINDISP); 1390 dtemp += MAXD(p->filter_dispersion + FREQ_TOLERANCE * (G.cur_time - p->lastpkt_recv_time) + abs_offset, MINDISP);
1348 G.rootdisp = p->lastpkt_rootdisp + dtemp; 1391 G.rootdisp = p->lastpkt_rootdisp + dtemp;
1349 VERB3 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted); 1392 VERB3 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted);
@@ -1433,7 +1476,8 @@ update_local_clock(peer_t *p)
1433 } 1476 }
1434#endif 1477#endif
1435 G.kernel_freq_drift = tmx.freq / 65536; 1478 G.kernel_freq_drift = tmx.freq / 65536;
1436 VERB2 bb_error_msg("update offset:%f, clock drift:%ld ppm", G.last_update_offset, G.kernel_freq_drift); 1479 VERB2 bb_error_msg("update peer:%s, offset:%f, clock drift:%ld ppm",
1480 p->p_dotted, G.last_update_offset, G.kernel_freq_drift);
1437 1481
1438 return 1; /* "ok to increase poll interval" */ 1482 return 1; /* "ok to increase poll interval" */
1439} 1483}