Процедура часовой фильтр (clock-filter)
Процедура часовой фильтр исполняется по прибытии сообщения NTP или другого события, в результате которого получены новые данные. Она использует аргументы (q, d, e), где q - результат измерения смещения часов, содержащийся в записи, а d и e соответственно RTT и дисперсия. Процедура определяет значение отфильтрованного смещения часов (filtered clock offset - peer.offset), RTT (peer.delay) и дисперсии (peer.dispersion). Она также корректирует дисперсию хранящихся записей и текущее показание часов (peer.update).
Процедура часового фильтра использует сдвиговый регистр (peer.filter), который состоит из NTP.SHIFT каскадов, каждый каскад содержит значения qi, di и e i, которые пронумерованы, начиная с нуля, слева направо. Фильтр инициализируется процедурой очистки при этом заносятся значения [0, 0, NTP.MAXDISPERSE] во всех каскадах. Новые данные записей вдвигаются в фильтр с левого конца. Пакетная процедура выдает записи в формате (q ,d, e), когда приходят новые корректирующие данные, в то время как процедура передачи выдает записи в форме [0, 0, NTP.MAXDISPERSE], когда истекает два периода запроса без поступления свежих данных. Когда одни и те же символы (q, d, e) используютсядля аргументов, содержимого часового фильтра и переменных партнера, их значения обычно понятно из контекста. Ниже представлена псевдопрограмма, поясняющая работу данной процедуры.
begin clock-filter procedure (q, d, e)
Дисперсия ei для всех корректных записей в регистре фильтра должна корректироваться с тем, чтобы отражать накопление смещения со времени последней коррекции. Эти записи заносятся также во временный список, следуя стандартному формату записей [расстояние, индекс]. Записи в регистре сдвигаются вправо, новые записи вводятся слева, а самая правая запись теряется. Временный список сортируется по значению расстояния. Если в списке не остается записей, процедура прерывается без корректировки переменных партнера.
for (i from ntp.size 1 to 1) begin | /* коррекция дисперсии */ |
[qi, di, ei] q{i-1}, d{i-1}, e{i-1}];
/* shift stage right */
ei = ei + ft;
add [li ? ei + {|di|}/2, i] to temporary list;
endfor;
[q0, d0, e0] q, d, e]; | /* ввести новую запись */ |
peer.update | /* сбросить показание часов */ |
где [distance index] представляет собой объединение полей расстояния и индекса (расстояние занимает старшую позицию). Дисперсия фильтра es вычисляется и включается в дисперсию партнера. Заметим, что временный список для этой цели уже упорядочен.
es
for (i from ntp.shift-1 to 0) | /* вычисление дисперсии фильтра */ |
- q0 > NTP.MAXDISPERSE)
es es + NTP.MAXDISPERSE) * NTP.FILTER;
else
es es + |qi
- q0|) * NTP.FILTER;
Смещение партнера q0, задержка d0 и дисперсия e0 выбираются как величины, соответствующие записи с минимальным расстоянием; другими словами, записи, соответствующей первому элементу временного списка (в данной нотации имеет индекс 0).
peer.offset q0; | /* корректировка переменных партнера */ |
peer.dispersion e0 + es, NTP.MAXDISPERSE);
end clock-filter procedure
Переменные peer.offset и peer.delay представляют смещение шкалы часов и RTT для локальных часов, измеренные относительно часов партнера. Обе они усредняются по большому числу измерений в течение длительного периода времени. Переменная peer.dispersion характеризует максимальную ошибку из-за неточности измерений, дрейфа и вариации записей. Все три переменные используются при выборе часов для синхронизации.