diff --git a/src/routing_layer/route_connectivity.h b/src/routing_layer/route_connectivity.h index 0a112a1c..2e7d3693 100644 --- a/src/routing_layer/route_connectivity.h +++ b/src/routing_layer/route_connectivity.h @@ -16,18 +16,23 @@ extern "C" { struct UTUN_INSTANCE; struct TOPO_GROUP; -// Запускает зондирование связности ко всем адресам удалённого узла +/* Запустить асинхронные пробы известных адресов nq из registry; group — его группа. + * UDP: до 8 сокетов, серия CONN_PROBE_COUNT с каждого до первого успешного сокета; + * TCP: один STCP ping с REALITY-параметрами при наличии. RTT — 0.1 мс, UINT16_MAX неизвестен. + * До 16 уникальных IP:port на семейство. Собственный/спящий узел и текущие пробы пропускаются; + * NAT/standby могут отложить старт. Результат — в nq->connectivity, завершение уведомляет topo callback. */ void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* nq); -// Отменяет все pending пробы для узла (при удалении / withdraw) +/* Отменить UDP/TCP-пробы и отложенный старт, освободить контексты; NULL допустим. + * Сбрасывает probe_status/pending_count, сохранённые RTT/status остаются. */ void route_connectivity_cancel_node(struct TOPO_GROUP_NODE* nq); -// Отменяет все pending пробы для всех узлов (при destroy) +// Отменяет pending пробы всех узлов во всех группах instance (при destroy) void route_connectivity_cancel_all(struct UTUN_INSTANCE* instance); // Устанавливает таймаут одного probe-пинга (по умолчанию CONN_PROBE_TIMEOUT_MS). -// Используется тестами для ускорения probe-циклов. +// Используется тестами для ускорения probe-циклов; настройка общая для процесса, 0 игнорируется. void route_connectivity_set_probe_timeout_ms(uint16_t ms); diff --git a/src/routing_layer/route_connectivity_doc.md b/src/routing_layer/route_connectivity_doc.md index ca292186..e3fc2055 100644 --- a/src/routing_layer/route_connectivity_doc.md +++ b/src/routing_layer/route_connectivity_doc.md @@ -1,64 +1,42 @@ -# route_connectivity — зондирование прямой связности с удалённым узлом +# route_connectivity — прямые пробы адресов узла -## 1. Назначение -Проверяет прямую IP-достижимость всех адресов удалённого узла через `etcp_send_ping_to_socket()`. -Для каждого адреса перебирает локальные сокеты-кандидаты (до 8), с каждого делает серию из 3 пингов -(CONN_PROBE_COUNT=3, CONN_PROBE_TIMEOUT_MS=1000). Результаты (reachable/unreachable, min_rtt) -сохраняются в `TOPO_CONNECTIVITY` узла и используются `conn_mgr` для выбора оптимального пути. +`route_connectivity_probe_node(instance, group, nq)` берёт общую запись узла из +registry и запускает асинхронные пробы. Собственный узел, пир в SLEEP-фазе и уже +идущие/отложенные пробы пропускаются. NAT-окно сохраняет незнакомые IP для проверки +входящих; Android standby откладывает старт до активного интервала. -В отличие от `route_ping` (пинг через BGP-посредника), здесь пинги идут напрямую с локальных сокетов -на адреса удалённого узла — без промежуточных узлов. +Для каждого семейства перебираются до 16 уникальных IP:port. Нулевые адреса/порты +пропускаются. Дедупликация выполняется по IP:port, без учёта типа адреса/протокола. -## 2. Как пользоваться -```c -// Запустить зондирование узла (вызывается conn_mgr при обнаружении нового узла): -route_connectivity_probe_node(instance, nodeq); +UDP проверяется с обычных локальных сокетов того же семейства (до 8). +IPv4-кандидаты фильтруются через `sock_match` в порядке списка сокетов; предпочтений +по /24 или рейтинга DIRECT/EIM здесь нет. Для IPv6 сначала идут сокеты той же /64, +затем остальные IPv6. TCP-сокеты и `probe_only` для UDP исключены. +С каждого UDP-сокета идёт последовательная серия из `CONN_PROBE_COUNT=3` ping; +достаточно одного ответа в серии, чтобы завершить этот адрес успешно. Следующий +сокет пробуется, если текущая серия не дала успеха. RTT — минимум успешной серии, +а не обязательный минимум по всем доступным сокетам. -// Отменить зондирование (при удалении узла / withdraw): -route_connectivity_cancel_node(instance, nodeq); +TCP-адрес проверяется одним `etcp_send_tcp_ping` через STCP-клиент, независимо +от набора UDP-сокетов. Используются REALITY-параметры из записи узла; адрес с +REALITY-флагом без параметров пропускается. Проба не создаёт READY-сессию группы. +Таймаут по умолчанию 1000 мс; `route_connectivity_set_probe_timeout_ms(ms)` меняет +его для новых контекстов всего процесса, 0 игнорируется. -// Отменить все зондирования (при destroy): -route_connectivity_cancel_all(instance); -``` +Результаты находятся в `nq->connectivity`: `probe_status`, `pending_count`, +`interface/nat/real_status`, соответствующие `*_min_rtt` и `*_probe_time`. +RTT и время — timebase (0.1 мс), UINT16_MAX означает неизвестный RTT. +INTERFACE обновляет также исторические поля REAL; отдельного третьего адреса +для этого не требуется. Успех одного адреса не затирается неудачей другого. +Завершение последней pending-пробы устанавливает DONE, обновляет БД и вызывает +`topo_fire_nodeinfo_cbk`. Если пригодных адресов/сокетов нет, DONE означает только +конец обхода: UNKNOWN не превращается автоматически в UNREACHABLE. -Результаты доступны через `nodeq->connectivity`: -- `probe_status` — `PROBE_STATUS_NONE` / `PROBE_STATUS_IN_PROGRESS` / `PROBE_STATUS_DONE` -- `interface_status/nat_status/real_status` — `PROBE_RESULT_UNKNOWN` / `REACHABLE` / `UNREACHABLE` -- `interface_min_rtt/nat_min_rtt/real_min_rtt` — минимальный RTT по всем сокетам (0.1ms) -- `pending_count` — счётчик незавершённых серий (когда 0 → PROBE_STATUS_DONE) +`route_connectivity_cancel_node(nq)` отменяет все UDP/TCP-пробы и отложенный старт, +освобождает контексты и сбрасывает probe_status/pending_count. Последние результаты +RTT/status сохраняются. Отмена нужна до удаления узла, группы или рабочих сокетов. +`route_connectivity_cancel_all(instance)` обходит все группы, не только UTUN. +Все вызовы выполняются в потоке ядра; group/nq заимствованы до завершения или отмены. -Ключевой нюанс: зондирование пропускает собственный узел (`nq->node->node_id == instance->node_id`). -Если зондирование уже в процессе, повторный вызов игнорируется. - -## 3. API - -### Внутренние структуры -| Структура | Назначение | -|-----------|------------| -| `conn_probe_ctx` | Контекст одной серии проб: `addr_type` (INTERFACE/NAT/REAL), `target_addr`, `candidate_sockets[8]`, `best_across_sockets` (min RTT по всем опробованным сокетам), `min_rtt` (в текущей серии), счётчики | - -### Подбор сокетов-кандидатов (`conn_match_candidate_sockets`) -Для каждого адреса узла подбирает локальные сокеты в порядке предпочтения: -1. **INTERFACE-адрес**: PRIVATE/LOCAL сокеты в той же /24 подсети -2. **NAT/REAL-адрес**: DIRECT > EIM > PUBLIC/UNKNOWN сокеты -3. Fallback: остальные подходящие сокеты, затем все IPv4 - -Для IPv6: предпочитает сокеты в той же /64 подсети. - -### Функции -| Функция | Назначение | -|---------|------------| -| `route_connectivity_probe_node(instance, nq)` | Перебрать все v4/v6 адреса узла, для каждого подобрать сокеты-кандидаты, запустить серии пингов по 3. Заполняет `nq->connectivity` | -| `route_connectivity_cancel_node(instance, nq)` | Сбросить `probe_status=NONE`, `pending_count=0`, занулить `nq` в ctx (чтобы callback не обновлял статистику) | -| `route_connectivity_cancel_all(instance)` | Сбросить состояние всех узлов в default-группе | - -### Логика завершения -- Серия из 3 пингов с одного сокета: если все 3 потеряны → переход к следующему сокету -- Если хоть 1 пинг успешен → серия считается успешной для данного адреса, обновляется `*_status=REACHABLE` и `*_min_rtt` -- Когда `pending_count` доходит до 0 → `probe_status = PROBE_STATUS_DONE` - -### Зависимости -- `src/etcp_connections.h` — `etcp_send_ping_to_socket()` (прямой пинг) -- `src/topo_node.h` — `TOPO_GROUP_NODE`, `TOPO_CONNECTIVITY`, `TOPO_ADDR4`, `TOPO_ADDR6` -- `src/topo_group.h` — `topo_groups_get_default()` (для cancel_all) -- `lib/u_async.h` — get_time_tb() для отметок времени +`route_ping` также выполняет прямые UDP-пробы, но для измерения наблюдаемого endpoint; +выбор наблюдателей/помощников и вычисление NAT-профиля находятся в `nat_detection`. diff --git a/src/routing_layer/routing_doc.md b/src/routing_layer/routing_doc.md index b904a554..d56f11ee 100644 --- a/src/routing_layer/routing_doc.md +++ b/src/routing_layer/routing_doc.md @@ -20,8 +20,13 @@ IPv6-пакеты на данный момент дропаются на эта **Ключевые нюансы:** - `routing_add_conn` / `routing_del_conn` — **deprecated** (no-op), маршруты теперь управляются через BGP и таблицу `route_lib` - Все не-IPv4 пакеты (IPv6, unknown) дропаются в `extract_dst_ip` -- Multicast (224.0.0.0/4) и limited broadcast (255.255.255.255) дропаются без логирования +- Multicast (224.0.0.0/4) и limited broadcast (255.255.255.255) отбрасываются с DEBUG-логом routing - Пакеты без маршрута дропаются с инкрементом `instance->dropped_packets` +- `route_pkt` забирает entry и dgram при любом исходе; ожидает `[cmd:1][IPv4]` и готовые `rt`/`tun`. +- Удалённая доставка идёт через `TOPO_GROUP_UTUN`; локальная — в `tun->input_queue`. + Firewall проверяется перед маршрутизацией выхода из TUN и перед локальной доставкой в TUN. +- Все вызовы выполняются в потоке ядра. `routing_destroy` снимает DATA binding и освобождает таблицу; + callback очереди TUN снимается при остановке самого TUN/UTUN-сервиса. ## 3. API