Guard routing loops and reconcile blocked transit against current paths
Track visited nodes outside the signed body for all routed packet types. Recheck queued transit routes without losing FIFO priority, reject unknown-group transit, and suppress BGP announcements caused only by RTT jitter.
Document routing rules and wire format. Validate graph churn, REINIT, encrypted transit, malformed paths, loop drops and queue cleanup; full suite: 106 passed, 1 skipped, plus proxy integration and sanitizer checks.
Числовое представление полей сохраняет существующий формат проекта (native endian). Отдельной версии/согласования формата нет; узлы должны обновляться совместно.
Полный пакет: `[SVC_ROUTE_HDR][payload][signature?][visited_ids:8*count][count:1]`.
Источник начинает список своим ID; транзит проверяет отсутствие собственного ID и дописывает его.
Правило действует для DATA, ACK и всех управляющих пакетов. Повторное посещение отбрасывается;
также проверяются размер, уникальность ID, первый ID=src и последний ID=ETCP peer.
Предел — 64 ID; на конечном узле полный список допустим, для следующего перехода места уже нет.
Список находится вне end-to-end подписи/шифрования и снимается перед crypto decode.
Это защита от временных петель при сходимости BGP, а не криптографическое подтверждение пути.
Маршруты строит BGP по правилам `topo_group.h`. Транзит использует текущий next hop.
При backpressure пакет ждёт в очереди; waiter и таймер 20 ms повторно проверяют маршрут.
Смена пути не требует освобождения старой физической очереди. ID добавляется один раз на приёме,
а не при каждой попытке выгрузки. При исчезновении маршрута транзит отбрасывается; доставку повторяет источник.
`reset_id` — случайный ненулевой ID локального экземпляра соединения; `peer_reset_id` — ID получателя. DATA, ACK и CLOSE принимаются только при совпадении обоих ID с текущей парой. Смена физического транспорта пару не меняет.
| Пакет | Флаги | Payload | Поля |
@ -31,7 +44,7 @@ Challenge защищает от случайных старых/перестав
- `send_q`: plaintext + seq + crypto mode, до 64 пакетов при обычной отправке. Кодирование происходит при отправке после handshake, с актуальной парой ID.
- `tx_seq`: следующий выделяемый seq; `tx_sent`: граница фактически отправленного; `tx_acked`: граница подтверждённого.
- `inflight_q`: финальные wire-копии, обычно до 256 пакетов. Копия создаётся до передачи в ETCP; ошибка не теряет pending-пакет.
- `inflight_q`: неизменяемое тело с подписью, без списка посещённых узлов, обычно до 256 пакетов. Каждый ретрансмит начинает новый список; ошибка не теряет pending-пакет.
- ACK принимается только в модульном интервале `(tx_acked, tx_sent]`. Дубликаты, старые и выходящие за границу ACK не продлевают ожидание прогресса. Удаляются существующие inflight-записи, а не перебираются все номера до произвольного ACK.
- Новые DATA и ретрансмиты идут по одному через waiter физической `send_input_q`. При смене пути отменяется waiter на очереди, где он действительно был зарегистрирован, включая уже запланированный callback.
- Каждые 300 ms без прогресса планируется проход повторной отправки. После 17 попыток без ACK соединение закрывается. Отсутствующий маршрут проверяется каждые 20 ms; очередь сохраняется. Пока первичный handshake не завершён, HELLO повторяется без отдельного таймаута.
@ -39,7 +52,7 @@ Challenge защищает от случайных старых/перестав
- Сброс физического ETCP сохраняет router inflight и seq. Восстановление самого ETCP-handshake остаётся обязанностью транспортного слоя.
- Crypto decode/проверка подписи выполняются до помещения в reorder и изменения rx_seq. Повреждённый пакет не подтверждается как доставленный.
- DATA выдаются сервису строго по seq; входящие дубликаты повторно проверяются после извлечения из очереди.
- Wire-пакет ограничен `PKTNORM_MAX_DGRAM_SIZE` (16384), включая заголовок и crypto overhead. Пустой payload запрещён: он используется для управления.
- Wire-пакет ограничен `PKTNORM_MAX_DGRAM_SIZE` (16384), включая заголовок, crypto overhead и резерв полного списка переходов. Пустой payload запрещён: он используется для управления.
## Сервисный API
@ -55,6 +68,12 @@ Callback может закрыть соединение. Освобождени
## Проверки и диагностика
`test_bgp_paths` использует настоящий BGP и роутер в управляемой сети четырёх узлов:
все 64 графа, разбиение/слияние, изменения при непустых очередях, REINIT, выбор кратчайшего пути
с устойчивым разрешением равенства. Дополнительно проверяет подписанный зашифрованный транзит,
петли DATA/ACK/control, повреждённые списки переходов, смену заблокированного next hop и очистку таймеров.
Счётчики `UTUN_INSTANCE.router_loop_drops` и `router_path_errors` сопровождаются WARN с идентичностью пакета.
`tests/test_etcp_router_faults` перехватывает SVC_ROUTE между настоящими роутерами, очередями и UASYNC-таймерами. Физическая очередь тестовая: нижележащий ETCP не скрывает потери от роутера. Проверяются:
1. Потери DATA/ACK, перестановка, дубликаты, четыре потока (два направления × два сервиса), backpressure и ограниченность физической очереди.