Correct connectivity probe and IPv4 routing documentation
This commit is contained in:
1 parent
0445c38c31
commit
bf03348c64
3 files changed
+50
-62
No files matched your search
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -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`.
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in new issue
Block a user