diff --git a/doc/etcp_multipath_plan.txt b/doc/etcp_multipath_plan.txt index b322d618..82bc3961 100644 --- a/doc/etcp_multipath_plan.txt +++ b/doc/etcp_multipath_plan.txt @@ -3,6 +3,63 @@ ETCP: независимая обратная связь каналов и до Статус +24.10.2026: уточнено и реализовано правило ретрансми́та. При наличии другого +initialized+UP канала повтор ждёт его cwnd/pacing, даже если прежний уже готов. +Без таких альтернатив разрешён прежний канал; DOWN последней альтернативы +пробуждает sender. ACK/control/burst-FILLER проходят во время ожидания DATA. +Курсор и номер попытки меняются только после принятия DATA транспортом. +Новых состояний, ресурсов и таймеров нет; формула RTO сохранена. + +Причины пауз разделены буферизованным трейсом первых800мс отказа: TX/RX/ACK, +снятие попытки, возврат в очередь, выбор пути, доставка сообщения и состояние очередей. +В slow-drop первый повтор начинается через232мс после отказа, ещё13мс занимает +доставка по рабочему пути. Исходная попытка достигла своего RTO около251мс; +разница объясняется временем в пути до включения отказа. При двух зависших +каналах ротация может последовательно выбрать оба, добавляя их ожидания RTO. +Под нагрузкой основная проблема — повторный выбор прежнего зависшего пути, +когда рабочая альтернатива занята pacer. В диагностическом load-drop за первые800мс +345 из677 повторов снова выбрали свой прежний путь; ожидание в send_q — медиана101мкс, +максимум2590мкс. Для load-hold —325 из676, медиана82мкс, максимум3503мкс. +Следовательно, перенос повтора из хвоста в голову не объясняет и не устраняет +основную паузу этих профилей. Такой диагностический контроль также не проходит +порог; изменение порядка очереди в производственный код не перенесено. +Исключение пути после RTO в отдельном контроле сокращает паузу load-drop до41мс, +но это диагностический опыт без полноценной модели проб/восстановления, +он не переносился в production. Исправлено именно правило ожидания альтернативы. + +Регрессия до исправления падает на отправке через готовый прежний путь при +заблокированном pacer другого UP-линка. После исправления windows44 сценария PASS +с управляемыми и реальными часами. Проверены ожидание cwnd/pacer без новых +попыток/таймеров, ACK и burst во время ожидания, освобождение альтернативы, +DOWN/удаление последней альтернативы, неинициализированный линк и поздний ACK. +Восемь профильных тестов ASAN/UBSan с detect_leaks=1 проходят без ошибок/утечек. + +Штатные профили отказов 8dd03c2b:7 из9 проходят прежние пороги. DROP/HOLD под +нагрузкой проходят каждый3/3: паузы43.172/44.755/43.493мс и40.965/39.796/44.982мс, +устойчивая полезная скорость7.189..7.476 из8Мбит/с оставшегося канала. +Для насыщенного источника тест ограничивает паузу и steady goodput, а не latency +каждого сообщения; измеренные максимальные latency102.572..114.403мс не скрыты. +Slow-drop остаётся FAIL: пауза238.569мс, latency264.727мс. Two-stuck — пауза219.338мс, +latency380.177мс. Это4 нарушения порогов; доставка/порядок/ресурсы проходят во всех9. +Скоростная матрица целиком после этого изменения не повторялась; дуплекс не закрыт. +Логи: /tmp/etcp-retry-alternative-{windows,real-time}.log, +/tmp/etcp-retry-alternative-asan-test_*.log, /tmp/etcp-retry-alternative--<1..3>.log/.csv. +Диагностические исходники/сборка: /tmp/etcp-recovery-probe.c/.mk; +логи /tmp/etcp-recovery-{trace,priority,exclude}-.log. + +Следующий отдельный шаг по отказам — ранний повтор до RTO, с сохранением окна +и метаданных исходной физической попытки до её ACK/RTO/close. Ротация уже не +возвращается в прежний путь при занятой альтернативе, но первый таймер не ускоряет. +Ранние копии должны иметь ограниченный бюджет и приоритет восстановления пропуска; +перед production нужно измерить цену дубликатов на исправных RTT20/200 каналах. +Нельзя автоматически считать раннюю копию потерей для BBR, обнулить чужой flight +или сократить штатный RTO медленного пути до100мс. Пауза<=100мс физически зависит +от готовности и задержки оставшегося пути; постоянная задержка100мс в одну сторону +уже не оставляет запаса на отправку и обработку. Эти ограничения требуют отдельного +проверенного правила срока/бюджета ранних копий; оно здесь не реализовано. + +Состояние после исправления pacer, до уточнения правила ретрансми́та: + Исправление pacer реализовано: таймер назначается на первый TB, разрешающий отправку, а не на полное погашение долга. Кредит и допустимый положительный долг по-прежнему ограничены 1мс; BBR/cwnd/min_rtt, RTO, wire-формат и порядок callbacks не менялись. @@ -530,10 +587,12 @@ load8/8 с 134217728 проверенными байтами за13.03с. Сет одного фрагмента — A->B->C->A; отправки других фрагментов и ACK его не меняют. Начать обход после last_link фрагмента, выбрать первый подходящий другой линк. Пропускать DOWN, неготовые, не вмещающие DATA и заблокированные pacer/транспортом. -Если готовых альтернатив нет, разрешён готовый прежний линк. Если не готов никто, -фрагмент ждёт штатного события ACK/pacer/transport-ready, без busy loop и нового RTO -для ещё не отправленной копии. Временно занятый следующий линк не блокирует поиск -остальных; отправлять без cwnd/pacing или ждать неограниченно именно его нельзя. +Если есть другой initialized+UP линк, прежний запрещён даже при временно занятых +альтернативах. Тогда фрагмент ждёт штатного события ACK/pacer/transport-ready, +без busy loop, новой попытки и нового RTO. Временно занятый следующий линк +не блокирует поиск остальных альтернатив. При отсутствии других initialized+UP +линков разрешён готовый прежний; DOWN последней альтернативы будит sender. +Отправлять без cwnd/pacing нельзя. Курсор удалённого линка очищается до free. Для первоначальной отправки остаётся обычный выбор по загрузке. Retry — отдельный режим той же функции выбора, с едиными проверками готовности, без второго набора diff --git a/doc/etcp_protocol.txt b/doc/etcp_protocol.txt index 526a5e0f..88a68ea4 100644 --- a/doc/etcp_protocol.txt +++ b/doc/etcp_protocol.txt @@ -13,8 +13,11 @@ HELLO/CHALLENGE/CONFIRM и keepalive передаются своим незав 2. Выбрать инициализированный UP-линк с готовым shaper и местом для целого DATA: inflight_bytes + длина DATA <= inflight_lim_bytes. Проверка выполняется без переполнения. Среди допустимых выбирается минимум inflight_bytes, при равенстве — round-robin. - Для повтора обход начинается после last_link самого фрагмента: первый готовый другой канал, - прежний канал — последним. Чужие DATA/ACK не меняют курсор фрагмента; удаления линка обнуляют его до free. + Для повтора обход начинается после last_link самого фрагмента: первый готовый другой канал. + Пока существует другой initialized+UP канал, прежний не используется: занятость альтернатив + по cwnd/pacing означает ожидание их события без создания новой попытки/RTO. + Прежний канал разрешён только при отсутствии таких альтернатив; DOWN последней альтернативы + пробуждает отправителя. Чужие DATA/ACK не меняют курсор фрагмента; удаление линка обнуляет его до free. 3. Если DATA не помещается, он остаётся в очереди; для накопленных ACK выбирается тот же линк, который принял соответствующий DATA, без ограничения DATA-cwnd/pacing. Кумулятивный till можно отправить по любому рабочему пути. ACK-only не увеличивает нагрузку DATA-shaper;