-
Notifications
You must be signed in to change notification settings - Fork 3
/
rate2.awk
193 lines (169 loc) · 4.63 KB
/
rate2.awk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/usr/bin/awk -f
# There are more comments below the following BEGIN block.
BEGIN {
# This value is in seconds.
# It must match the -i interval used with ntpclient if not
# the default of 10 minutes.
td = 10 * 60;
# How many milliseconds may a sample be off by (system time) and
# still be counted?
# This check (with the above td) is here to tell you if you have
# several ntpclient processes logging to the same file.
tderr = 100;
# How many ppm may one sample's computed frequency differ from the
# previous one and still be counted?
# This check filters out records resulting from an NTP server glitch.
freq_diff = 5;
# How many milliseconds may it take to get an answer from the
# ntp server?
# Long replies often produce glitchy results.
ntp_delay = 100;
}
# This script is to determine what your /etc/ntp.adj should be
# It is invoked thusly:
# awk -f rate2.awk < /var/lib/ntp.log
# Unlike the original rate.awk script supplied with ntpclient,
# this one can be run against the log of a running ntpclient which
# is adjusting the adjtimex frequency. The alternative is a drag
# because it means you cannot be keeping time while you are determining
# a suitable adjtimex frequency. You, of course, can do that with
# this program too; you just don't have to. Given a file that works
# with the original rate.awk, this script should produce similar
# results. You may have to increase the above thresholds to keep
# records from being ignored so you get the same answers.
# It is assumed that nothing besides ntpclient is adjusting that
# value for the duration of the creation of the log file.
# It is recommended that you collect lots of log entries.
# It is further recommended that you collect logs for roughly an
# integer number of days to even out daily cycles (temperature, etc.)
# No tweaking necessary below here, I hope.
function pretty_time(ss, dd, hh, mm, ret, f) {
ss += 0;
if(ss < 0) {
ret = "-";
ss = -ss;
} else {
ret = "";
}
mm = int(ss / 60); ss -= (mm * 60);
hh = int(mm / 60); mm -= (hh * 60);
dd = int(hh / 24); hh -= (dd * 24);
if(dd != 0) {
ret = sprintf("%s%d+", ret, dd);
}
if(ret != "" || hh != 0) {
ret = sprintf("%s%02d:", ret, hh);
}
if(ret != "" || mm != 0) {
ret = sprintf("%s%02d:", ret, mm);
}
ss = sprintf("%06.3f", ss); sub(/0+$/, "", ss); sub(/\.$/, "", ss);
if(ret != "" || (ss + 0) != 0) {
ret = sprintf("%s%s", ret, ss);
} else {
ret = "0";
}
return ret;
}
function abs(a) {
a += 0;
if(a < 0) {
return -a;
}
else {
return a;
}
}
function round(a, p) {
p += 0;
if(p == 0) {
return int(a + 0.5);
} else {
return int((a / p) + 0.5) * p;
}
}
BEGIN {
f1 = "";
tderr = tderr / 1000;
tdmin = td - tderr;
tdmax = td + tderr;
freq_diff = freq_diff * 65536;
ntp_delay = ntp_delay * 1000;
c = 0;
ignored = 0;
delta_o = 0;
delta_t = 0;
sum_f2 = 0;
min_f2 = "init";
max_f2 = "init";
prev_f2 = "init";
}
/^[0-9]/ {
if(f1 == "") {
t1 = $1 * 86400 + $2;
o1 = $5;
f1 = $7;
t2 = ts = t1;
o2 = o1;
fs = f1;
c++;
} else {
t2 = $1 * 86400 + $2;
o2 = $5;
td = t2 - t1;
od = o2 - o1;
if($3 > ntp_delay) {
print "Ignoring: ntp delay (" $3 / 1000 " ms) out of spec in line " FNR ".";
ignored++;
} else {
if(td < tdmin || td > tdmax) {
print "Ignoring: time difference (" pretty_time(td) ") out of spec in line " FNR ".";
ignored++;
} else {
f2 = f1 + (65536 * od / td);
if(prev_f2 == "init") {prev_f2 = f2;}
if(abs(f2 - prev_f2) > freq_diff) {
print "Ignoring: target frequency adjustment (" (f2 - prev_f2) / 65536 " ppm) out of spec in line " FNR ".";
ignored++;
} else {
# weigted average
sum_f2 += f2 * td;
delta_o += od;
delta_t += td;
# minimum / maximum
if(min_f2 == "init") { min_f2 = f2; }
else { if(f2 < min_f2) { min_f2 = f2; }}
if(max_f2 == "init") { max_f2 = f2; }
else { if(f2 > max_f2) { max_f2 = f2; }}
c++;
}
prev_f2 = f2;
}
}
t1 = t2;
o1 = o2;
f1 = $7;
}
}
END {
if(ignored > 0) {
print "";
}
print "total time:",pretty_time(round(delta_t));
print "number of samples:",c;
if(ignored > 0) {
print "ignored samples:", ignored, "(" round(100 * ignored / (ignored + c)) "%)";
}
if(delta_t >= tdmin) {
print "";
slope = delta_o / delta_t;
f2 = sum_f2 / delta_t;
print "delta-t", delta_t, "seconds"
print "delta-o", delta_o, "useconds"
print "slope:", slope, "ppm";
print "old frequency:", fs, "(" fs / 65536,"ppm)";
# print "min frequency:", int(min_f2 + .5), "(" min_f2 / 65536,"ppm)";
# print "max frequency:", int(max_f2 + .5), "(" max_f2 / 65536,"ppm)";
print "new frequency:", int(f2 + .5), "(" f2 / 65536,"ppm)";
}
}