Files
utun2/src/ntp_node_time_doc.md
T

35 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NTP Node Time
## 1. Назначение
Обмен временем с прямыми ETCP-пирами. Если у узла ещё нет поправки, он принимает время синхронизированного пира с оценкой сетевой задержки. Поправка хранится в `instance->ntp` и применяется getters из `ntp_time.h`; часы ОС не меняются. Отключение интернет-NTP (`ntp.enabled=0`) не отключает этот обмен. Уже синхронизированный узел повторно не принимает поправку от пиров, но интернет-NTP может её обновить.
## 2. Как пользоваться
В uasync-потоке после создания `instance->connections` вызвать `ntp_node_time_init()`. Он привязывает raw packet ID `ETCP_ID_NTP_TIME = 0x04` (прямой ETCP, без роутера), подписывается на новые соединения и на INIT всех существующих, в том числе pending. На INIT отправляется `TIME_SYNC`; при запуске модуля пакет также отправляется уже инициализированным соединениям. Повторный активный init возвращает 0 без дублирования подписок. При занятом ID или ошибке регистрации возвращается -1; свои частичные регистрации снимаются.
`TIME_SYNC` — 10 байт: ID (1), flags (1, bit 0 = synced), время отправителя (int64 Unix мкс в нативном порядке байтов). Синхронизированный отправитель передаёт скорректированное время, остальные — локальное. При первом сообщении сохраняется исходное смещение для диагностики. Если получатель не синхронизирован, а отправитель синхронизирован, применяется:
`offset_us = local_receive_us - sender_us - mean_link_rtt_us / 2`.
Среднее RTT — арифметическое по всем элементам `conn->links`, включая нулевые значения и down-линки; `rtt_last` переводится из 0,1 мс в микросекунды. При отсутствии линков задержка считается нулевой. Это приближённая оценка: симметричность пути и точность часов пира не гарантируются.
После принятия поправки устанавливаются `ntp.synced` и `ntp.last_sync_tb`, затем время рассылается остальным. Синхронизированный получатель отвечает несинхронизированному отправителю. Когда оба синхронизированы, ответа нет — бесконечный обмен не возникает. Полученный entry и его dgram освобождаются при обработке, в том числе при заполненном кеше диагностики.
`ntp_node_sync_peers()` рассылает время по соединениям с `initialized && links_up`, если модуль активен и есть поправка. Вызывается также после успешной интернет-NTP-синхронизации.
**Нюансы:**
- Кеш содержит до 32 диагностических записей, а не ограничивает число соседей. При заполнении вытесняется запись с наименьшим `last_seen_tb` (при равенстве — первая по индексу); исходное смещение новой записи сбрасывается.
- Диагностическое смещение — `raw_local_receive_us - sender_us`, без вычитания задержки. Оно отличается от глобальной поправки, принятой с оценкой половины RTT.
- При повторном сообщении модуль сравнивает смещение с предыдущим. Модуль разности строго >2 с даёт WARN, строго >10 с — ERROR. Это изменение относительного смещения: оно может включать коррекцию часов отправителя и изменение задержки, а не только дрейф часов.
- `destroy` вызывается в uasync-потоке вне callbacks модуля/соединений. Снимает raw binding, подписку новых соединений и свои callbacks со всех текущих соединений, очищает кеш. Глобальную поправку не меняет. Повторный вызов и NULL безопасны.
## 3. API
**Структуры:**
- `struct NTP_NODE_PEER` — ID пира, предыдущее диагностическое смещение, наличие исходного значения и время последнего обновления.
- `struct NTP_NODE_TIME` — кеш, число занятых записей и флаг активности; контракты полей/функций описаны в `ntp_node_time.h`.
**Функции:**
- `ntp_node_time_init(inst)` — 0 при успехе/уже активном модуле, -1 при ошибке; inst и очередь connections обязательны.
- `ntp_node_time_destroy(inst)` — снимает регистрации и очищает кеш, сохраняя глобальную поправку.
- `ntp_node_sync_peers(inst)` — рассылает время готовым прямым соседям; для NULL/неактивного/несинхронизированного модуля ничего не делает.