Record RTT feedback experiments and refine multipath recovery plan
This commit is contained in:
1 parent
7e0a0905e5
commit
259dfa35d9
2 files changed
+229
-18
No files matched your search
@@ -0,0 +1,197 @@
|
||||
ETCP: независимая обратная связь каналов и доставка при отказах
|
||||
Проверка архитектуры и план следующего изменения, 23.10.2026
|
||||
|
||||
Статус
|
||||
|
||||
Бюджет очереди BBR уже реализован в fix/etcp-multipath-recovery: 20мс в PROBE_BW,
|
||||
все резервы входят в предел max(4*MSS, BDP + BW*20мс). Это мягкая цель модели;
|
||||
STARTUP/DRAIN, сериализация и обратный трафик не дают гарантии физической очереди <=20мс.
|
||||
В штатном тесте equal получено 14.464/16Мбит/с, bandwidth — 9.060/10Мбит/с;
|
||||
очередь медленного канала в bandwidth сократилась примерно с 47 до 21мс.
|
||||
Изменения протокола и учёта попыток ниже ещё не реализованы.
|
||||
|
||||
Что подтверждено кодом и диагностикой
|
||||
|
||||
1. ACK выбирает канал независимо от DATA: select_link(conn, 0), inflight/RR.
|
||||
Одна общая ack_q смешивает подтверждения DATA разных каналов. Поэтому интервал
|
||||
delivery sample включает фактический обратный путь ACK, а rtt_us берётся
|
||||
из отдельного timestamp-обмена last_link. Для RTT 20/200мс измерены возвраты
|
||||
быстрых DATA через медленный канал за >=112мс при RTT модели около 24мс.
|
||||
Это несовместимые исходные данные для BDP, pacing и бюджета очереди.
|
||||
|
||||
2. Общий ACK.till вызывает тот же etcp_ack_recv(), что и явный ACK элемента.
|
||||
Даже если явные ACK возвращать своим путём, till подтверждает DATA других
|
||||
каналов и обновляет их BBR в чужой момент времени. Перенаправить ACK недостаточно.
|
||||
|
||||
3. INFLIGHT_PACKET хранит только последнюю попытку: last_link, last_timestamp,
|
||||
delivery snapshots. При повторе они заменяются, ACK содержит только общий seq.
|
||||
Поздний ACK старой копии может быть приписан новой попытке и другому каналу.
|
||||
Неоднозначны и RTT, и скорость, и выбор окна, которое освобождается.
|
||||
|
||||
4. В начальном pacing есть отдельный дефект. bbr_update_min_rtt() устанавливает
|
||||
has_seen_rtt до bbr_set_pacing_rate(), поэтому предусмотренная инициализация
|
||||
на первом RTT пропускается. Её аргумент также ошибочен: передаётся B/s вместо
|
||||
размера окна в байтах. Затем перевод pacing в целые Kbit/s превращает малую
|
||||
ненулевую скорость в 0, который shaper трактует как unlimited. Обновление
|
||||
скорости само по себе не пересчитывает уже поставленный shaper-таймер.
|
||||
|
||||
5. RTO общий, основан на RTT/jitter соединения. Очередь wait_ack просматривается
|
||||
как FIFO с единым timeout; индивидуальные дедлайны с такой остановкой обхода
|
||||
несовместимы. Повтор может снова уйти в зависший канал.
|
||||
|
||||
6. Поток собирается по общему seq: при RTT 20/200мс разность времени доставки
|
||||
неизбежно создаёт переупорядочивание. Исправление ACK не устраняет ожидание
|
||||
пропущенного фрагмента. В диагностике при высокой скорости накоплено порядка
|
||||
0.17–0.29MB. Память сборки и пауза приложения требуют отдельных проверок.
|
||||
|
||||
7. stcp_link_send() подтверждает постановку в tx_queue. Это не означает прогресс
|
||||
записи в TCP. Для stalled TCP одной проверки link_status/cwnd/pacer недостаточно.
|
||||
|
||||
Экспериментальная проверка причин
|
||||
|
||||
Диагностический бинарник /tmp/etcp-rtt-experiment включает штатный multipath-стенд
|
||||
и настоящее ядро. Подмена происходит через linker --wrap, исходники протокола
|
||||
не менялись. Используются реальные шифрование, UDP, dummynet и проверка порядка,
|
||||
содержимого, полного завершения доставки, таймеров и счётчика выделений.
|
||||
|
||||
Контроль RTT 20/200мс, 8+8Мбит/с, с начальным pacing от окна/RTT:
|
||||
- после завершения STARTUP полезная скорость 8.055/16Мбит/с, быстрый канал 0.633;
|
||||
- свой путь ACK, без обновления BBR через till, фактический RTT попытки:
|
||||
8.831 и 8.945/16Мбит/с; длинный канал недогружен;
|
||||
- дополнительно исключены неоднозначные повторы из оценки скорости:
|
||||
14.127 и 14.559/16Мбит/с, проверки установившегося режима прошли.
|
||||
|
||||
С последним вариантом дополнительно проверены RTT20/200мс при разных BWlim:
|
||||
- 2+8Мбит/с (fast-distant): полезная скорость 8.735/10Мбит/с;
|
||||
- 8+2Мбит/с (slow-distant): полезная скорость 8.979/10Мбит/с.
|
||||
Проверки каждого канала, суммарной скорости, очереди и полного drain прошли.
|
||||
В агрегате максимум очереди составил соответственно 24.9/26.4мс и 22.6/27.6мс.
|
||||
Для равной BW выполнено два успешных повтора, для разных BW — по одному;
|
||||
этого достаточно для выбора направления, но не для заявления о полной устойчивости.
|
||||
Контроль последнего варианта по штатному rtt с фиксированным прогревом 3с:
|
||||
14.312/16Мбит/с, очереди в агрегате 23.4/24.9мс, failures=0.
|
||||
Это один успешный прогон диагностического прототипа, а не всего рабочего ядра.
|
||||
|
||||
Выборочные логи показывают преждевременный выход длинного канала из STARTUP
|
||||
с заниженной оценкой BW. До фильтрации в модель попадал sample от повторной
|
||||
передачи: RTT отвергнут, но delivery interval и скорость использованы.
|
||||
Это подтверждает необходимость идентификации попытки; фильтр по send_count
|
||||
годится для диагностики, но теряет достоверные измерения повторов и не заменяет ID.
|
||||
|
||||
Успешный единичный запуск без полного разделения учёта давал 14.45Мбит/с,
|
||||
но повторные проверки выявили нестабильность. Он не является критерием готовности.
|
||||
Отдельный прогрев до выхода из STARTUP использован только для диагностики:
|
||||
штатные требования к разгону, очереди и утилизации не ослаблялись.
|
||||
Фильтрация till в последнем прототипе сохраняет кумулятивную границу rx_ack_till;
|
||||
её удаление из протокола сломало бы ограничение окна приёмника.
|
||||
Прототип не проверяет новый wire-формат, владение попытками или отказоустойчивость.
|
||||
|
||||
Предлагаемый контракт
|
||||
|
||||
Разделить логическую доставку фрагмента и физическую попытку передачи.
|
||||
|
||||
- Логический объект: общий seq, payload, признак доставки. Он отвечает за порядок
|
||||
потока, unacked_bytes приложения и очередь повторной доставки.
|
||||
- Попытка: уникальный uint64 attempt_id, ссылка на канал, seq, размер, время
|
||||
отправки, delivery snapshots и состояние учёта окна. Последующая отправка
|
||||
создаёт новую попытку; предыдущие снимки остаются неизменными.
|
||||
- attempt_id монотонен в пределах согласованной ETCP-сессии и не переиспользуется
|
||||
при удалении/создании линка. Перезапуск счётчика допустим только с новой эпохой,
|
||||
когда DATA/ACK старой сессии уже отклоняются. Переполнение закрывает сессию.
|
||||
- DATA содержит seq + attempt_id. ACK элемента содержит attempt_id и ограниченную
|
||||
задержку получателя. Задержка передаётся без короткого modulo-wrap; переполнение
|
||||
помечает измерение недействительным. Пересчитать DATA MSS, MTU и ACK batching.
|
||||
- Подтверждение попытки возвращается через тот же ETCP_LINK, где она принята.
|
||||
Очередь ACK принадлежит линку; piggyback содержит только ACK этого линка.
|
||||
Дубликат логического DATA с новым attempt_id тоже подтверждается.
|
||||
- BBR обновляется по реально подтверждённой попытке своего канала. RTT — elapsed
|
||||
этой попытки минус допустимый receiver delay. KA RTT остаётся метрикой живости.
|
||||
ACK другого канала не формирует sample. ACK/control по-прежнему обходят только
|
||||
локальный DATA-pacer; общая физическая очередь коммуникации сохраняется.
|
||||
- Общий till остаётся подтверждением логической доставки и места приёмника.
|
||||
Он может прийти по любому живому пути, освобождает payload/очередь повторов,
|
||||
но не придумывает доставку попытки, RTT/BW или освобождение чужого окна.
|
||||
- Доставка приложения учитывается один раз. Физические попытки учитываются
|
||||
каждая в своей модели; их суммарная доставка может включать дубликаты DATA.
|
||||
- ACK или объявление потери освобождает окно попытки ровно один раз. Поздний ACK
|
||||
не дебетует его повторно. После доставки payload можно освободить, метаданные
|
||||
других попыток живут до ACK/потери/закрытия, без удержания лишнего payload.
|
||||
История ограничена по числу и сроку; неизвестный старый ID безопасно игнорируется.
|
||||
- Удаление линка/сессии отменяет его таймеры, удаляет ACK и попытки, освобождает
|
||||
учёт ровно один раз. Не хранить указатель на уже освобождённый ETCP_LINK.
|
||||
|
||||
Почему не общий самый быстрый обратный канал
|
||||
|
||||
Такой выбор не согласует интервалы и не устраняет неоднозначность повторов.
|
||||
Понадобится учитывать смену обратного маршрута в каждой модели, а отказ общей
|
||||
обратной дороги затронет остальные прямые пути. Собственный ACK сохраняет одну
|
||||
модель на канал и независимость отказов. Общая логическая граница при этом
|
||||
может распространяться любым рабочим каналом.
|
||||
|
||||
Последовательность реализации и критерии завершения
|
||||
|
||||
1. Начальный pacing как отдельное исправление без смены wire-формата.
|
||||
Инициализировать от настоящего начального окна и первого валидного RTT.
|
||||
Сохранить точные B/s до shaper, отделить unlimited от округления. При смене
|
||||
ставки пересчитать оставшийся pacing-долг и таймер, не создавая новый burst.
|
||||
Проверки: короткий служебный DATA -> пауза -> bulk, RTT20/200мс, скорость ниже
|
||||
1Kbit/s, увеличение/уменьшение ставки с активным таймером, полный STARTUP.
|
||||
|
||||
2. Цельный переход на логические фрагменты и идентифицируемые попытки.
|
||||
Добавить индекс attempt_id в очереди попыток каждого линка и отдельную ACK-очередь.
|
||||
Общий индекс попыток не нужен: ACK ищется на принявшем его линке.
|
||||
Разделить обработчики logical till и ACK попытки; одновременно обновить DATA,
|
||||
ACK, декодеры, MTU/MSS, lifecycle и .h. Не оставлять промежуточный формат,
|
||||
в котором новый ACK продолжает обращаться только к last_link.
|
||||
Проверки: первая копия A -> повтор B -> поздний ACK A; обратный порядок ACK;
|
||||
ACK дубликат; чужой/неизвестный ID; till с другого пути; link recreation;
|
||||
потеря ACK при уже доставленном payload; close/reset с активными попытками.
|
||||
После этого повторить всю матрицу скоростей. Балансировщик менять только
|
||||
при сохраняющейся недогрузке: эксперименты уже показывают полную утилизацию
|
||||
без смены алгоритма выбора DATA, поэтому дополнительная эвристика пока лишняя.
|
||||
|
||||
3. Независимые сроки и восстановление каналов.
|
||||
RTT/RTO и таймер старейшей попытки принадлежат каналу. FIFO допустима только
|
||||
при одном текущем RTO для всех его попыток; пересчитывать таймер при его смене.
|
||||
При потере ограничить новые DATA на проблемном пути, пробовать восстановление
|
||||
ограниченными probe, повторять недоставленные DATA через рабочие каналы.
|
||||
Не отправлять следующий bulk вслепую в тот же застрявший путь.
|
||||
Проверки: DROP/HOLD отдельно по направлениям и вместе, несколько застрявших
|
||||
каналов, возврат старых копий после HOLD, повторный отказ, смена RTT/BW на ходу.
|
||||
|
||||
4. Учёт нижележащей очереди STCP.
|
||||
Ограниченный tx_queue и уведомление о реальном прогрессе/готовности должны
|
||||
участвовать в выборе пути. Определить время начала попытки и учёт данных,
|
||||
принятых STCP, но ещё не записанных в сокет; не смешивать их с wire delivery.
|
||||
Проверки: полностью остановленная TCP-запись рядом с рабочим UDP/STCP,
|
||||
последующий выпуск очереди, закрытие соединения и отсутствие роста памяти.
|
||||
|
||||
Общие проверки
|
||||
|
||||
Матрица: equal, bandwidth, rtt, fast-distant, slow-distant, three, bidirectional.
|
||||
Отдельно измерять время STARTUP, steady goodput, очередь каждого направления,
|
||||
переупорядочивание, повторы и паузу приложения. Отчёт содержит данные каждого
|
||||
повтора и минимум, а не только лучший результат. Не выполнять сетевые замеры
|
||||
параллельно. Сохранить исходные пороги штатного test_etcp_multipath.
|
||||
|
||||
Добавить асимметричные прямой/обратный пути, ACK compression, поздние копии,
|
||||
потери ACK и исчерпание лимитов памяти. Проверять счётчики по очередям, однократный
|
||||
учёт подтверждения попытки и одну логическую доставку; утечки/UAF — ASAN/UBSan.
|
||||
Логи: session/seq/attempt_id, DATA link, ACK link, send/receive/ack times,
|
||||
receiver delay, причина retire, inflight до/после и вход/выход BBR.
|
||||
|
||||
Проверено для текущего бюджета: BBR18/18, windows16 сценариев, шесть транспортных
|
||||
ASAN/UBSan тестов с detect_leaks=1 PASS. Общий check.sh: 180/183; FAIL
|
||||
test_nat_detection_faults, test_nat_detection, test_encrypted_attachment.
|
||||
Эти падения внесены отдельной задачей; связь с BBR не установлена.
|
||||
|
||||
Логи опытов: /tmp/etcp-rtt-ab-baseline.log,
|
||||
/tmp/etcp-rtt-settled-control.log, /tmp/etcp-rtt-settled-candidate-diagnostic.log,
|
||||
/tmp/etcp-rtt-settled-karn.log, /tmp/etcp-rtt-settled-karn-repeat.log,
|
||||
/tmp/etcp-rtt-settled-fast-distant.log, /tmp/etcp-rtt-settled-slow-distant.log,
|
||||
/tmp/etcp-rtt-original-karn.log.
|
||||
Сборка диагностического бинарника:
|
||||
make -C tests -f Makefile -f /tmp/etcp-rtt-experiment.mk /tmp/etcp-rtt-experiment
|
||||
Основной повтор:
|
||||
RTT_SETTLED=1 RTT_SEED=1 RTT_SAME_ACK=1 RTT_NO_CUM=1 RTT_ACTUAL=1 RTT_KARN_RATE=1 \
|
||||
/tmp/etcp-rtt-experiment rtt
|
||||
+32
-18
@@ -21,7 +21,7 @@
|
||||
при разных RTT/BWlim не выполняются требования утилизации, в том числе из-за повторов и переполнения очередей.
|
||||
Базовые исправления BBR/pacing внесены 23.10.2026 в fix/etcp-multipath-recovery (см. завершённую подзадачу ниже).
|
||||
Выбор пути повторов, общий RTO и блокировка сборки ещё не исправлены.
|
||||
Финальный прогон девяти отказов: drop-reverse/short-hold PASS, остальные семь FAIL по целевым требованиям;
|
||||
Прогон девяти отказов до бюджета очереди: drop-reverse/short-hold PASS, остальные семь FAIL по целевым требованиям;
|
||||
повтор на обычных часах slow-drop: пауза 450мс, latency 1267мс. Trace показывает повторную отправку в зависший путь.
|
||||
Связанные регрессии 5/5 PASS. ASAN/UBSan + detect_leaks=1: calibration и short-hold PASS;
|
||||
slow-drop сохраняет функциональный FAIL, ошибок санитайзеров/утечек во всех трёх запусках нет.
|
||||
@@ -31,22 +31,35 @@
|
||||
После исправлений добавить смену профилей на ходу, повторяющиеся отказы и смешанный UDP/STCP со stalled TCP write.
|
||||
Полная матрица дольше 90s общего runner и запускается отдельной целью; нарушения завершают её с ошибкой.
|
||||
Окно PROBE_RTT и DATA MSS согласованы 23.10.2026 (см. завершённую подзадачу ниже).
|
||||
Одиночный канал RTT=200мс/BWlim=8Мбит/с теперь проходит: полезная скорость 6.99Мбит/с, очередь <=133.1мс.
|
||||
Далее согласовать обратную связь: ACK выбирает путь по inflight/RR, скорость оценивается по фактическому времени
|
||||
возврата ACK, а RTT модели берётся из отдельного timestamp-обмена исходного линка. Это разные интервалы.
|
||||
При повторах ACK не идентифицирует попытку: запись хранит только last_link, старый ACK может быть приписан новому пути.
|
||||
Нужен явный контракт учёта попыток до изменения выбора пути/повторов; простой запрет прошлого линка его не заменяет.
|
||||
После этого исправлять здоровье линка, независимые сроки повторов и доставку при DROP/HOLD по существующим тестам.
|
||||
Профили после исправления окна: equal PASS (14.75 из 16 Мбит/с), bandwidth по скорости PASS (9.11 из 10),
|
||||
но очередь 47.9мс >40мс. RTT 20/200мс: 10.08 из 16 Мбит/с, быстрый путь недогружен; rtt FAIL.
|
||||
Пороги очереди и утилизации не ослаблены. Логи: /tmp/etcp-probe-{equal,bandwidth,rtt}.log/.csv.
|
||||
Диагностика bandwidth с состояниями модели: /tmp/etcp-probe-bandwidth-diagnostic.log.
|
||||
Дополнительная проверка 23.10: /tmp/etcp-queue-budget.log/.csv; лог включает bw Q16, DATA MSS, ACK-резерв и пик очереди.
|
||||
Пик штатного PROBE_UP: bw=16465/65536 байт/мкс, min_rtt=24000мкс, MSS=1097;
|
||||
2*BDP=12060, ACK-резерв=1893, 2*MSS=2194, cwnd=16147 байт. Сложение и единицы на этом пике корректны.
|
||||
Профиль bandwidth даёт полезные 9.045 из 10Мбит/с, очередь 47.1мс >40мс; порог теста не изменён.
|
||||
Для следующей правки требуется выбрать политику: добавить бюджет задержки к BBR либо сохранить штатные резервы
|
||||
и обосновать допустимый предел очереди с учётом сериализации. Вопрос передан пользователю; алгоритм пока не изменён.
|
||||
Пользователь выбрал бюджет задержки; реализация и проверки завершены (см. подзадачу ниже).
|
||||
После бюджета equal PASS (14.464 из 16 Мбит/с), bandwidth PASS (9.060 из 10), очередь медленного пути
|
||||
25мс отдельно / 20.7мс в агрегате. RTT 20/200мс остаётся FAIL: 7.1–7.7 из 16 Мбит/с, быстрый путь недогружен.
|
||||
Пороги очереди и утилизации не ослаблены. Логи: /tmp/etcp-queue-limited-{equal,bandwidth,rtt}.log/.csv.
|
||||
Диагностика подтвердила несовместимость интервалов ACK и отдельного RTT last_link, обновление чужого BBR
|
||||
через общий till и неоднозначность ACK повторов. Найден отдельный дефект начального pacing от окна/RTT.
|
||||
Подробные причины, проверенный контракт попыток, этапы и критерии: [doc/etcp_multipath_plan.txt](etcp_multipath_plan.txt).
|
||||
Диагностический прототип без правок протокола: после разгона контроль 8.055/16Мбит/с; свой путь ACK,
|
||||
отдельный till и RTT попытки без фильтрации неоднозначной скорости дают лишь 8.831–8.945/16.
|
||||
После фильтрации неоднозначных повторов — 14.127 и 14.559/16Мбит/с, steady-проверки PASS.
|
||||
Разные BWlim 2+8 и 8+2Мбит/с при RTT20/200мс: 8.735 и 8.979/10Мбит/с, steady PASS.
|
||||
Контроль прототипа по штатному rtt с прогревом 3с: 14.312/16Мбит/с, очередь 23.4/24.9мс, PASS.
|
||||
Это проверка причин, а не реализация новой архитектуры: нужны attempt_id, владение очередями и lifecycle.
|
||||
Начать с начального pacing, затем согласованно разделить логический seq и физические попытки/ACK,
|
||||
после этого исправлять сроки/здоровье линка и DROP/HOLD. Смену DATA-балансировщика пока не навязывать:
|
||||
прототип уже утилизирует пути без неё. Штатные проверки разгона и отказов остаются обязательными.
|
||||
|
||||
[+] **ETCP/BBR: бюджет очереди в установившемся режиме** — реализовано 23.10.2026 по выбору пользователя:
|
||||
В PROBE_BW окно ограничено max(4*MSS, BDP + BW*20мс), с насыщением арифметики и учётом ACK/PROBE_UP резервов
|
||||
внутри общего предела. Ограничение применяется также на fast path и до callback. 0 отключает политику.
|
||||
STARTUP/DRAIN не ограничены этим бюджетом; это мягкая цель модели, а не гарантия физической очереди <=20мс.
|
||||
До политики bandwidth давал очередь 47.1–47.9мс >40мс при корректных единицах и сложении резервов;
|
||||
после политики профиль проходит по скорости и очереди, equal также PASS. Разные RTT и отказы не закрыты.
|
||||
BBR 18/18, windows 16 сценариев PASS; BBR/windows/session/transport/STCP traffic/NCD ASAN/UBSan
|
||||
с detect_leaks=1: 6/6 PASS. Полный check.sh: 180/183, FAIL NAT detection/fault и encrypted_attachment;
|
||||
связь падений с BBR не установлена, отдельная открытая задача сохраняется.
|
||||
Логи: /tmp/etcp-queue-budget-fastpath.log, /tmp/etcp-queue-budget-windows.log,
|
||||
/tmp/etcp-queue-limited-asan-results.log, /tmp/etcp-queue-limited-asan-test_*.log,
|
||||
/tmp/etcp-queue-limited-full-check.log. Политика описана в etcp_bbr.h, etcp_bbr_doc.md и doc/etcp_protocol.txt.
|
||||
|
||||
[+] **ETCP/BBR: единое окно DATA и корректное осушение PROBE_RTT** — исправлено 23.10.2026:
|
||||
BBR использует MSS=normalizer->frag_size, а не wire-MTU/размер STCP-кадра. Начальное окно UDP/STCP равно 4*MSS;
|
||||
@@ -88,10 +101,11 @@
|
||||
После исправления окна BBR общий прогон снова 181/183: encrypted_attachment PASS, но FAIL оба NAT-теста.
|
||||
test_nat_detection_faults упал в run_case mode=1 (UNKNOWN/contact_history); test_nat_detection не дождался профиля
|
||||
за 18с на socket=udp. Его отдельный повтор тоже упал, уже на socket=second, с той же причиной contact_history/UNKNOWN.
|
||||
После бюджета очереди полный check.sh: 180/183, повторились оба NAT-падения и encrypted_attachment.
|
||||
Связь с изменениями BBR не установлена. Разобрать фикстуры/таймеры по логам, не ослаблять ожидания.
|
||||
Логи: tests/logs/test_nat_detection_faults.log, tests/logs/test_encrypted_attachment.log,
|
||||
/tmp/etcp-recovery-nat-retry.log, /tmp/etcp-recovery-attachment-retry.log,
|
||||
/tmp/etcp-probe-full-check.log, /tmp/etcp-probe-nat-retry.log.
|
||||
/tmp/etcp-probe-full-check.log, /tmp/etcp-probe-nat-retry.log, /tmp/etcp-queue-limited-full-check.log.
|
||||
|
||||
[+] **ETCP: единый установщик прямого транспорта через NCD** — исправлено 22.10.2026:
|
||||
Удалён неиспользуемый рабочим кодом etcp_connect с EARLY/LATE, отдельными линками и таймерами;
|
||||
|
||||
Reference in new issue
Block a user