Align topology model documentation with current runtime contracts
This commit is contained in:
1 parent
c282d03f25
commit
94aaf3c8e3
2 files changed
+122
-159
No files matched your search
@@ -209,7 +209,7 @@ struct TOPO_NODEPATH {
|
||||
uint64_t exchange; // local_epoch сессии, в которой путь подтверждён NODEINFO
|
||||
};
|
||||
|
||||
/** Узел в контексте группы (per-group данные). Хранится в TOPO_GROUP->nodes (ll_queue). */
|
||||
/** Узел группы: удалённый хранится в TOPO_GROUP->nodes (ll_queue), локальный — отдельно в local_node. */
|
||||
struct TOPO_GROUP_NODE {
|
||||
struct ll_entry ll; // queue entry, хеш-ключ 8 байт → node_id
|
||||
uint64_t node_id; // идентификатор узла в этой группе
|
||||
@@ -249,8 +249,8 @@ struct TOPO_GROUP_NODE* topo_node_find_by_id(struct TOPO_GROUP* group, uint64_t
|
||||
void topo_nodeq_free_group_fields(struct TOPO_GROUPS* groups, struct TOPO_GROUP_NODE* nq);
|
||||
/* Освободить принадлежащие узлу записи путей и их контейнер; ETCP-соединения заимствованы. */
|
||||
void topo_nodeq_clear_paths(struct TOPO_GROUP_NODE* nq);
|
||||
/* Полное удаление узла из группы: отменяет влётные пробы, освобождает paths/subnets,
|
||||
* убирает из group->nodes и освобождает сам nq. Единственный корректный способ удаления узла. */
|
||||
/* Полное удаление узла из group->nodes: отменяет пробы, освобождает paths/subnets,
|
||||
* убирает из очереди и освобождает nq. local_node освобождает владелец группы отдельно. */
|
||||
void topo_nodeq_remove_node(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* nq);
|
||||
|
||||
/* Размер переменной части NODEINFO или -1 при NULL/счётчиках подсетей без TOPO_FLAG_SEND_SUBNETS. */
|
||||
@@ -289,7 +289,7 @@ int topo_node_init_self(struct UTUN_INSTANCE* instance);
|
||||
int topo_node_update_my_addresses(struct UTUN_INSTANCE* instance);
|
||||
/* Обработчик изменений локального сокета: обновляет адреса узла. */
|
||||
void topo_node_on_socket_changed(struct ETCP_SOCKET* sock, int event, void* arg);
|
||||
/* Вывести диагностику узлов группы в лог категории BGP на уровне INFO. */
|
||||
/* Вывести group->nodes в лог категории BGP на уровне INFO; отдельный local_node не добавляется. */
|
||||
void topo_node_dump_all(struct TOPO_GROUP* group);
|
||||
/* Записать дамп в buf: длина без NUL или -1 при ошибке форматирования. Ёмкость ограничена INT_MAX.
|
||||
* При усечении завершает запись сразу, заменяет хвост доступной частью "\n[TRUNCATED]\n" и возвращает реальную длину.
|
||||
|
||||
+118
-155
@@ -1,189 +1,152 @@
|
||||
# topo_node
|
||||
# topo_node — модель, снимок и локальное состояние узла
|
||||
|
||||
## 1. Назначение
|
||||
## Два уровня записи
|
||||
|
||||
Модель данных узла топологии — структуры для представления узла в памяти, сериализации/
|
||||
десериализации в бинарный wire-формат для BGP-обмена, глобальный реестр идентичностей
|
||||
(refcounting) и диагностический дамп.
|
||||
TOPO_NODE содержит общую идентичность: node_id, диагностический ver, timestamp, ключи,
|
||||
Ed25519-подпись, имя, тип/активность, списки SOCKMETA4/ADDR4/SOCKMETA6/ADDR6/REALITY.
|
||||
Групповых flags, group_id, подсетей и путей в нём нет.
|
||||
|
||||
Модуль определяет два слоя:
|
||||
- **Память:** связанные списки (`TOPO_ADDR4`, `TOPO_SOCKMETA4`, `TOPO_SUBNET4` и др.) и две
|
||||
структуры узла — `TOPO_NODE` (глобальная идентичность) и `TOPO_GROUP_NODE` (per-group данные).
|
||||
- **Wire-формат:** packed-структуры (`TOPOMSG_NODE`, `TOPOMSG_ADDR4` и др.) для передачи по сети.
|
||||
TOPO_GROUP_NODE содержит node_id, подсети, пути, last_ver/last_timestamp, состояние conn_mgr,
|
||||
пробы связности, presence/up, radio/phone_status и заимствованный NCD handle.
|
||||
Удалённые записи находятся в group->nodes; локальная запись хранится отдельно в group->local_node.
|
||||
TOPO_NODEPATH содержит заимствованный ETCP_CONN, hop_count, cumulative_rtt, exchange
|
||||
и массив uint64_t[hop_count] непосредственно после структуры.
|
||||
|
||||
Сам модуль не содержит сетевой логики BGP-обмена — этим занимается `topo_group`. Здесь только
|
||||
данные и их упаковка/распаковка. Персистентность — в `topo_node_sqlite`.
|
||||
Все операции выполняются в uasync-потоке ядра. BGP-сессией/обменом управляет topo_group,
|
||||
хранением в общей SQLite — topo_node_sqlite. Этот модуль также готовит локальную запись,
|
||||
обновляет адреса и инициирует рассылку после их изменения.
|
||||
|
||||
Два уровня представления узла:
|
||||
- **TOPO_NODE** — глобальная идентичность (pubkeys, имя, адреса, self-signature). Хранится один
|
||||
раз в глобальном реестре `TOPO_GROUPS->node_registry` (hash по node_id), разделяется между
|
||||
группами через `group_ref_count`.
|
||||
- **TOPO_GROUP_NODE** — узел в контексте группы: `node_id`, `paths`, `subnets`, `last_ver`,
|
||||
`connectivity`, `conn_presence/conn_up`, `handle`. Хранится в `TOPO_GROUP->nodes`.
|
||||
## Реестр и память
|
||||
|
||||
## 2. Как пользоваться
|
||||
node_registry хранит отдельный ll_entry с node_id и указателем TOPO_NODE.
|
||||
registry_find возвращает заимствованный указатель. Для удержания записи берётся registry_ref;
|
||||
последний registry_unref удаляет registry entry, списки, имя и сам объект.
|
||||
|
||||
### Типовые сценарии
|
||||
registry_store принимает входной объект при успехе и возвращает запись с одной новой ссылкой:
|
||||
|
||||
**Сборка информации о себе:**
|
||||
```c
|
||||
topo_group_update_my_nodeinfo(instance, group);
|
||||
```
|
||||
Строит `group->local_node` (`TOPO_GROUP_NODE`) из конфига: сокеты, адреса (interface/NAT/real),
|
||||
подсети; при изменениях инкрементирует `ver`. Для chat-групп (`TOPO_GROUP_TYPE_CHAT`) подсети
|
||||
не включаются.
|
||||
- Более свежий подписанный timestamp заменяет всю запись, включая пустые списки, но адрес существующего объекта сохраняется.
|
||||
- Старый/равный вход освобождается, возвращается прежняя запись. Конфликт одинаковых timestamp логируется.
|
||||
- Для двух bootstrap-записей с timestamp=0 сливаются присутствующие списки; полноценная идентичность может обновить скалярные поля.
|
||||
- При новой регистрации более свежий/равный сохранённый снимок SQLite может заменить вход.
|
||||
- При NULL-результате вход остаётся у вызывающего.
|
||||
|
||||
**Сериализация для отправки по BGP:**
|
||||
```c
|
||||
struct TOPO_NODE* ni = topo_node_registry_find(groups, nq->node_id);
|
||||
uint8_t buf[4096];
|
||||
int len = topo_node_serialize(ni, nq, group_id, flags, buf, sizeof(buf), cumulative_rtt);
|
||||
```
|
||||
Запаковывает `TOPO_NODE` + per-group данные (`TOPO_GROUP_NODE`) в буфер: заголовок
|
||||
`TOPOMSG_NODE`, затем имя, SOCKMETA4, ADDR4, SOCKMETA6, ADDR6, REALITY-сокеты,
|
||||
подсети (если `TOPO_FLAG_SEND_SUBNETS`) и hop-лист (через `topo_node_best_hop_list`).
|
||||
Без флага подсети не записываются, а оба их счётчика в заголовке равны нулю.
|
||||
У зарегистрированной записи используется registry_unref. Незарегистрированный результат parser/SQL
|
||||
уничтожается topo_node_destroy(groups, ni). Списки сокетов/адресов/подсетей принадлежат пулам groups,
|
||||
имя, REALITY, контейнер подсетей и отдельно возвращённый hop-list — u_malloc/u_calloc.
|
||||
Для освобождения pooled-списков нужен тот же контейнер groups.
|
||||
|
||||
**Десериализация при получении NODEINFO:**
|
||||
```c
|
||||
struct TOPO_NODE* ni = NULL;
|
||||
struct TOPO_NODESUBNETS* subnets = NULL;
|
||||
uint64_t* hop_list = NULL; uint8_t hop_count = 0;
|
||||
uint16_t cumulative_rtt = 0;
|
||||
topo_node_deserialize(group, data, data_len, &ni, &subnets, &hop_list, &hop_count, &cumulative_rtt);
|
||||
```
|
||||
При успехе (0) восстанавливает `TOPO_NODE` (через `u_calloc`) и запрошенные подсети/hop-лист.
|
||||
`out_ni` обязателен; остальные выходы независимы и могут быть NULL. Все присутствующие
|
||||
секции проходят проверку и занимают своё место в пакете, даже если их выход не запрошен.
|
||||
Проверяются точная длина, согласованность флага/счётчиков подсетей, профили и длины префиксов.
|
||||
Подпись и допустимость BGP-пути проверяются отдельно. При ошибке (-1) выходы обнулены,
|
||||
частичные объекты освобождены. Освобождение успешного результата:
|
||||
topo_nodeq_free_group_fields снимает ссылку реестра, освобождает подсети и обнуляет handle;
|
||||
сам nq и пути остаются. topo_nodeq_clear_paths освобождает пути/контейнер, транспорт не закрывает.
|
||||
Удалённый узел удаляется через topo_nodeq_remove_node: отмена проб, удаление IPv4-маршрутов,
|
||||
удаление из очереди и освобождение полей/записи. local_node освобождает владелец группы отдельно.
|
||||
|
||||
- `topo_node_destroy(groups, ni)` — освободить `TOPO_NODE` (списки адресов + имя).
|
||||
- Подсети передаются в `TOPO_GROUP_NODE`; `topo_nodeq_free_group_fields` освобождает их и снимает registry ref.
|
||||
Контейнер/записи путей освобождает отдельный `topo_nodeq_clear_paths`. Для целого узла используют `topo_nodeq_remove_node`.
|
||||
- `u_free(hop_list)` — освободить отдельно выделенный массив переходов.
|
||||
## Timestamp и подпись
|
||||
|
||||
**Поиск узла по ID:**
|
||||
```c
|
||||
struct TOPO_GROUP_NODE* nq = topo_node_find_by_id(group, node_id); // per-group
|
||||
struct TOPO_NODE* ni = topo_node_registry_find(groups, node_id); // глобальная идентичность
|
||||
```
|
||||
timestamp — Unix microseconds, версия всей подписанной записи; 0 обозначает bootstrap.
|
||||
ver — циклический счётчик 1..255, не фильтр свежести. Групповой last_timestamp хранит последнюю
|
||||
принятую версию в этой группе, last_ver используется для диагностики.
|
||||
|
||||
**Дамп всех узлов:**
|
||||
```c
|
||||
topo_node_dump_all(group); // в лог
|
||||
topo_node_format_all(group, buf, size); // в строку
|
||||
```
|
||||
topo_node_build_sig_msg создаёт канонические байты в таком порядке:
|
||||
|
||||
### Ключевые концепции
|
||||
| Поле/секция | Представление подписи |
|
||||
| --- | --- |
|
||||
| node_id, ver | uint64 в нативном порядке, затем байт ver |
|
||||
| timestamp | 8 байт BE |
|
||||
| public_key | X25519, 32 байта |
|
||||
| node_name | До 63 байт и NUL |
|
||||
| client_type, client_activity | По одному байту |
|
||||
| Счётчики | По байту: v4 sockets, v4 addrs, v6 sockets, v6 addrs, REALITY |
|
||||
| SOCKMETA4, ADDR4, SOCKMETA6, ADDR6 | Полные списки в текущем порядке; адреса сетевыми байтами, порты LE |
|
||||
| REALITY | socket_id, short_id[8], server_pubkey[32], version[3], SNI с NUL |
|
||||
|
||||
- **Глобальный реестр**: `TOPO_NODE` хранится один раз в `node_registry`; `topo_node_registry_store`
|
||||
дедуплицирует по `node_id` (возвращает существующий при совпадении). `registry_ref/unref`
|
||||
управляют `group_ref_count`; при 0 — `topo_node_destroy`.
|
||||
- **Путь**: `TOPO_NODEPATH = {conn, hop_count, cumulative_rtt}` + inline `hop_list[hop_count]`
|
||||
сразу после структуры. Полный hop-лист для отправки — `topo_node_best_hop_list`.
|
||||
- **Self-signature**: `x25519_self_sig` — Ed25519-подпись над каноническим сообщением
|
||||
(`topo_node_build_sig_msg`: pubkey || имя || client_type || client_activity || адреса).
|
||||
Ставится `topo_node_sign_self`, проверяется в `topo_group_process_nodeinfo`.
|
||||
- **Адреса трёх типов**: `TOPO_ADDR_INTERFACE` (LAN), `TOPO_ADDR_NAT` (после детекции),
|
||||
`TOPO_ADDR_REAL` (подтверждённый прямой). Для каждого сокета — до 3 адресов.
|
||||
- **TOPO_CONNECTIVITY** — локальное состояние связности (не передаётся по BGP): probe_status
|
||||
(NONE/IN_PROGRESS/DONE/DEFERRED), RTT и статусы interface/nat/real, `probe_deferred_wait`.
|
||||
- **TOPO_FLAG_SEND_SUBNETS** — если установлен, подсети сериализуются; для chat-групп сброшен.
|
||||
Ненулевые счётчики подсетей без флага недопустимы, в том числе при `out_subnets=NULL`.
|
||||
- **Wire-протокол**: заголовок `TOPOMSG_NODE` (packed) + динамика: `node_name`, `SOCKMETA4*N`,
|
||||
`ADDR4*N`, `SOCKMETA6*N`, `ADDR6*N`, REALITY-сокеты, опционально подсети, hop-лист.
|
||||
`topo_node_dyn_size()` возвращает размер динамики либо -1 при некорректном сочетании флага/счётчиков.
|
||||
SOCKMETA содержит id/config_type/mapping/inbound/source, каждый по байту.
|
||||
Групповые flags/id, подсети, hops и cumulative_rtt не входят в подпись.
|
||||
Ed25519-ключ передаётся в записи и используется при verify; он не добавляется отдельным полем канонического сообщения.
|
||||
|
||||
## 3. API
|
||||
topo_node_sign_self назначает timestamp строго выше текущего и сохранённого в SQLite,
|
||||
подписывает ключом instance->my_ed25519_privkey и сохраняет снимок, если БД есть.
|
||||
При ошибке восстанавливаются timestamp/подпись; другие изменённые вызывающим поля не откатываются.
|
||||
Поэтому локальные обновления подписывают временный candidate до замены общей записи.
|
||||
|
||||
### Основные структуры
|
||||
topo_node_verify проверяет диапазон timestamp, node_id=derive(X25519 public_key)
|
||||
и Ed25519-подпись предоставленным ключом; возвращает 0/-1.
|
||||
Проверку права участия в группе и допустимости пути выполняет вызывающий BGP-слой.
|
||||
|
||||
| Структура | Назначение |
|
||||
|-----------|-----------|
|
||||
| `struct TOPO_NODE` | Глобальная идентичность узла: `flags`, `group_id`, `node_id`, `ver`, `public_key`, `ed25519_public_key`, `x25519_self_sig`, `client_type`, `client_activity`, `node_name`, списки v4/v6 sock_meta и addrs, `group_ref_count` |
|
||||
| `struct TOPO_GROUP_NODE` | Per-group запись: `node_id`, `subnets`, `paths` (queue TOPO_NODEPATH), `last_ver`, `conn_mgr_*`, `connectivity`, `conn_presence`, `conn_up`, `handle` (ncd) |
|
||||
| `struct TOPO_NODEPATH` | Путь через ETCP_CONN: `{conn, hop_count, cumulative_rtt}` + inline `hop_list[]` |
|
||||
| `struct TOPO_NODESUBNETS` | v4/v6 подсети узла (отдельный malloc, может быть NULL) |
|
||||
| `struct TOPO_CONNECTIVITY` | Связность: probe_status, RTT, статусы interface/nat/real, probe-тайминги |
|
||||
| `struct TOPOMSG_NODE` | Packed-заголовок wire-формата: счётчики, `hop_count`, `client_type/activity`, `cumulative_rtt` |
|
||||
| `struct TOPOMSG_ADDR4/6` | Packed wire одного адреса (addr, port, type, socket_id, protocol) |
|
||||
| `struct TOPOMSG_SOCKMETA4/6` | Packed wire сокет-метаданных (id, config_type, nat_type) |
|
||||
| `struct TOPOMSG_SUBNET4/6` | Packed wire подсети (addr, prefix_length) |
|
||||
## NODEINFO wire
|
||||
|
||||
### Вспомогательные типы в памяти (связанные списки)
|
||||
Сериализация ручная, без lib/serialize. Packed-заголовок TOPOMSG_NODE содержит поля записи,
|
||||
group_id/flags, счётчики, hop_count и cumulative_rtt. Далее идут:
|
||||
|
||||
| Тип | Назначение |
|
||||
|-----|-----------|
|
||||
| `struct TOPO_SOCKMETA4/6` | Элемент списка сокет-метаданных (next*, id, config_type, nat_type) |
|
||||
| `struct TOPO_ADDR4/6` | Элемент списка адресов (next*, addr, port, type, socket_id, protocol) |
|
||||
| `struct TOPO_SUBNET4/6` | Элемент списка подсетей (next*, addr, prefix_length) |
|
||||
| Порядок | Секция |
|
||||
| --- | --- |
|
||||
| 1 | node_name_len байт имени без NUL |
|
||||
| 2 | SOCKMETA4, затем ADDR4 |
|
||||
| 3 | SOCKMETA6, затем ADDR6 |
|
||||
| 4 | REALITY с фиксированным полем server_name[256] |
|
||||
| 5 | SUBNET4, затем SUBNET6, только с TOPO_FLAG_SEND_SUBNETS |
|
||||
| 6 | hop_count идентификаторов uint64_t |
|
||||
|
||||
Элементы списков аллоцируются из memory pool'ов (`topo_groups`) через `memory_pool_alloc/free`.
|
||||
Числа wire копируются в нативном порядке; IP — сетевые байты. Это представление отличается
|
||||
от канонического сообщения подписи (timestamp BE, порты LE, строки с NUL).
|
||||
Счётчики ограничены 255, имя — 63 байтами. dyn_size возвращает размер динамики или -1.
|
||||
|
||||
### Константы
|
||||
serialize получает ni и nq, оставляет владение у вызывающего и возвращает длину либо -1.
|
||||
Входные поля должны быть пригодны для публикации; serialize не проверяет подпись.
|
||||
Hop-list берётся один раз из выбранного живого пути. Radio и phone_status дополняют flags.
|
||||
Без TOPO_FLAG_SEND_SUBNETS счётчики подсетей равны 0; секции не записываются.
|
||||
|
||||
| Константа | Значение | Назначение |
|
||||
|-----------|---------|-----------|
|
||||
| `TOPO_ADDR_INTERFACE` / `TOPO_ADDR_NAT` / `TOPO_ADDR_REAL` | 0/1/2 | Тип адреса |
|
||||
| `TOPO_PROTO_UDP` / `TOPO_PROTO_TCP` | 0x01/0x02 | Транспорт |
|
||||
| `ADDR_TYPE_NETIF/DIRECT/NAT_EIM/NAT_STRICT` | 0/1/2/3 | Классификация адреса |
|
||||
| `PROBE_STATUS_NONE/IN_PROGRESS/DONE/DEFERRED` | 0/1/2/3 | Состояние пробы |
|
||||
| `PROBE_RESULT_UNKNOWN/REACHABLE/UNREACHABLE` | 0/1/2 | Результат пробы |
|
||||
| `CONN_TYPE_NONE/DIRECT/REVERSE/INDIRECT` | 0/1/2/3 | Стратегия соединения |
|
||||
| `CLIENT_TYPE_SERVER/DESKTOP/MOBILE` | 0/1/2 | Тип клиента |
|
||||
| `CLIENT_ACTIVITY_STANDBY/ACTIVE` | 0/1 | Режим |
|
||||
| `NCONN_DIRECT/INDIRECT/BGP` | 1/2/4 | Биты наличия соединений |
|
||||
| `TOPO_FLAG_SEND_SUBNETS` | 0x01 | Отправлять подсети |
|
||||
| `TOPO_GROUP_UTUN` | `0x8000000000000000ULL` | ID utun-группы по умолчанию |
|
||||
| `TOPO_GROUP_TYPE_UTUN/CHAT` | 1/2 | Тип группы |
|
||||
| `CONN_MGR_MAX_INTERMEDIARIES` | 3 | Максимум посредников |
|
||||
deserialize требует group->instance->topo_groups с пулами и обязательный out_ni.
|
||||
Остальные out_* независимы и необязательны. Проверяются точная длина, флаг/счётчики,
|
||||
профили сокетов и IPv4 /0..32, IPv6 /0..128. Все секции обходятся и проверяются независимо
|
||||
от запрошенных выходов. Подпись и допустимость BGP-пути проверяются отдельно.
|
||||
|
||||
### Функции
|
||||
Перед разбором переданные выходы обнуляются, прежние объекты не освобождаются.
|
||||
Успех — 0 и атомарная выдача результата; ошибка — -1 и NULL/0 без частичных объектов.
|
||||
Пустые секции дают NULL/0. ni уничтожается topo_node_destroy, подсети передаются владельцу
|
||||
TOPO_GROUP_NODE, hop-list освобождается u_free.
|
||||
|
||||
**Реестр и refcounting:**
|
||||
- `topo_node_registry_find(groups, node_id)` — найти `TOPO_NODE` в глобальном реестре.
|
||||
- `topo_node_registry_store(groups, ni)` — сохранить с дедупликацией (возвращает существующий при совпадении).
|
||||
- `topo_node_registry_ref/unref(groups, node_id)` — инкремент/декремент `group_ref_count`.
|
||||
- `topo_node_destroy(groups, ni)` — освободить `TOPO_NODE` (списки адресов + имя).
|
||||
## Локальная публикация
|
||||
|
||||
**Per-group:**
|
||||
- `topo_node_find_by_id(group, node_id)` — найти `TOPO_GROUP_NODE` по node_id (hash).
|
||||
- `topo_nodeq_free_group_fields(groups, nq)` — освободить per-group поля (subnets, paths) + unref глобального TOPO_NODE.
|
||||
topo_node_init_self создаёт подписанную идентичность с отдельной ссылкой ядра; 0/-1.
|
||||
|
||||
**Сериализация:**
|
||||
- `topo_node_dyn_size(msg)` — размер динамической части по счётчикам заголовка.
|
||||
- `topo_node_serialize(ni, nq, group_id, flags, out, out_max, cumulative_rtt)` — сериализовать `TOPO_NODE` + per-group в буфер.
|
||||
- `topo_node_deserialize(group, data, len, &out_ni, &out_subnets, &out_hop_list, &out_hop_count, &out_cumulative_rtt)` — восстановить из wire-формата.
|
||||
topo_group_update_my_nodeinfo готовит local_node из имени, ключей, типа/активности,
|
||||
radio/phone_status и конфигурационных подсетей. Сравниваются адреса и префиксы,
|
||||
включая замену подсети при прежнем количестве. CHAT не анонсирует подсети.
|
||||
|
||||
**Пути:**
|
||||
- `topo_node_best_hop_list(nq, &out_count, &out_rtt)` — лучший hop-лист (по min hop_count).
|
||||
Новая запись/подсети готовятся до удаления прежнего local_node. IPv4 проходит route_insert
|
||||
с запретом пересечений; при конфликте или отказе подготовки/подписи прежние узел и маршруты сохраняются.
|
||||
Общая подписанная идентичность заменяется после успешного sign_self.
|
||||
Возврат — число IPv4-подсетей (CHAT: 0), при ошибке -1. Рассылку запускает вызывающий.
|
||||
|
||||
**Подпись:**
|
||||
- `topo_node_build_sig_msg(ni, buf, buf_size)` — каноническое сообщение для Ed25519-подписи.
|
||||
- `topo_node_sign_self(instance, ni)` — подписать свой NODEINFO (`x25519_self_sig`).
|
||||
topo_node_update_my_addresses отдельно собирает адреса рабочих UDP/TCP-сокетов.
|
||||
PRIVATE исключаются, UDP probe_only исключаются; LOCAL остаются доступными для локальных подключений.
|
||||
UDP публикует интерфейс и допустимый наблюдаемый NAT endpoint, IPv6 интерфейс — отдельным списком.
|
||||
TCP может публиковать внешний IP с port=0, если входящий порт неизвестен.
|
||||
REALITY-параметры берутся из глобальной конфигурации и связываются с socket_id.
|
||||
|
||||
**Обновление о себе:**
|
||||
- `topo_group_update_my_nodeinfo(instance, group)` — перестроить `local_node`.
|
||||
- `topo_node_update_my_addresses(instance)` — обновить адреса.
|
||||
- `topo_node_on_socket_changed(sock, event, arg)` — обработчик изменений сокетов.
|
||||
Изменение подписывается/сохраняется до замены списков и рассылается во все группы.
|
||||
Неизменный набор не переподписывается, но SQL-проекция обновляется повторно.
|
||||
Возврат 1/0/-1; ошибка проекции может дать -1 уже после применённой подписанной записи.
|
||||
on_socket_changed инициирует этот пересчёт при событии сокета.
|
||||
|
||||
**Диагностика:**
|
||||
- `topo_node_dump_all(group)` / `topo_node_format_all(group, buf, size)` — дамп узлов.
|
||||
## Пути, RTT и диагностика
|
||||
|
||||
**Inline-аксессоры (.h):**
|
||||
- `topo_v4_sock_meta/addr`, `topo_v6_sock_meta/addr`, `topo_v4_subnets/topo_v6_subnets`, `topo_list_count`.
|
||||
best_path выбирает путь с conn->links_up, без close_requested, по минимуму hop_count,
|
||||
при равенстве — меньшему peer_node_id. READY проверяется отдельно владельцем групповой сессии.
|
||||
best_hop_list возвращает заимствованный inline-массив; out_count обязателен,
|
||||
out_rtt необязателен и получает RTT без локального линка. При отсутствии пути — NULL/0.
|
||||
|
||||
### Зависимости
|
||||
topo_get_chain_rtt складывает rtt_last локального соединения и cumulative_rtt.
|
||||
UINT16_MAX обозначает неизвестный путь/локальный RTT либо насыщение суммы.
|
||||
Единицы RTT и timebase-таймингов связности — 0.1 ms.
|
||||
|
||||
| Модуль | Использование |
|
||||
|--------|--------------|
|
||||
| `ll_queue.h` | `TOPO_GROUP_NODE` — запись в очереди (hash по node_id), `paths` — вложенная очередь |
|
||||
| `secure_channel.h` | `SC_PUBKEY_SIZE` (32) |
|
||||
| `mem.h` | `u_malloc`, `u_calloc`, `u_free` |
|
||||
| `memory_pool.h` | Элементы списков из пулов `topo_groups` |
|
||||
| `debug_config.h` | Логирование (BGP) |
|
||||
| `topo_group.h` | `struct TOPO_GROUP`, `TOPO_GROUPS` |
|
||||
| `route_lib.h` | `route_insert/route_delete` |
|
||||
| `utun_instance.h` | `struct UTUN_INSTANCE` |
|
||||
ping_request_cbk сообщает, пора ли повторить ping хотя бы в одной группе (TTL 24 часа).
|
||||
ping_update_rtt обновляет время ping и минимальные RTT во всех группах, SQL и callbacks;
|
||||
сам по себе не переводит статусы достижимости в REACHABLE.
|
||||
|
||||
dump_all пишет group->nodes в BGP/INFO. format_all форматирует ту же очередь в буфер:
|
||||
реальная длина без NUL, -1 при ошибке форматирования, некорректные аргументы дают 0.
|
||||
При наличии буфера строка завершена NUL; после первого усечения запись прекращается,
|
||||
хвост заменяется доступной частью маркера TRUNCATED. Ёмкость ограничена INT_MAX.
|
||||
|
||||
Полные объявления и контракты — в topo_node.h; общий жизненный цикл снимка — doc/node_snapshot.md.
|
||||
Reference in new issue
Block a user