Bound ETCP receive window and fix timestamp and allocator UB
This commit is contained in:
1 parent
59f4802904
commit
03f71fd94e
10 files changed
+211
-47
No files matched your search
@@ -6,10 +6,10 @@
|
||||
Промежуточный прогон: 96 passed, 1 failed, 1 skipped; оставался `test_chat_join_e2e`.
|
||||
После KEY_REGISTER_ACK и исправления невыровненных чтений повторный полный
|
||||
`make check -j4`: **97 passed, 0 failed, 1 skipped (98)**.
|
||||
Лог: `/tmp/utun-ack-final-check.log`. Пропущенный `test_auto_socket_dynamic`
|
||||
запущен отдельно с root в изолированной сети и упал — подробности ниже.
|
||||
Внешние `check-proxy/check-burst/check-load` не выполнялись: цепочка root-проверок
|
||||
остановилась на этом тесте.
|
||||
Лог: `/tmp/utun-ack-final-check.log`. Исходное падение отдельного root-теста и
|
||||
последующая доработка описаны ниже. После исправления autosockets общий набор дал
|
||||
97 PASS / 1 SKIP, а `check-proxy`, `check-burst`, `check-load` прошли:
|
||||
`/tmp/root-fix-full-check.log`.
|
||||
|
||||
`test_etcp_lifecycle`, `test_etcp_link_stress`, `test_conn_mgr_phases` дополнительно
|
||||
прошли ASan/UBSan/LeakSanitizer. Инструментированы тесты и изменённые транспортные/
|
||||
@@ -110,15 +110,59 @@ GUI получает request_id в событии и игнорирует уст
|
||||
В конфиге теста включён auto_sockets, но не отключён стандартный фильтр
|
||||
`auto_socket_skip_no_default_route=1`. Dummy-интерфейсы теста не имеют default route,
|
||||
а `auto_socket.c:reconcile_iface()` исключает такие интерфейсы. Лог показывает
|
||||
`no links created`, затем TIMEOUT. Для локального сценария тест должен явно задать
|
||||
`auto_socket_skip_no_default_route=no` и проверить создание сокетов до трафика.
|
||||
`no links created`, затем TIMEOUT. Исправленный тест создаёт собственный network
|
||||
namespace, поднимает loopback и добавляет default route только клиентским dummy.
|
||||
Фильтр остаётся включённым; отдельно проверяется исключение серверного dummy,
|
||||
иначе его сокет скрывал бы полный обрыв клиентской сети.
|
||||
|
||||
Кроме того, тест сохраняет handle общего дедлайна, traffic_send и traffic_monitor
|
||||
в одну переменную timeout_handle; фазовые таймеры вообще не сохраняются. При выходе
|
||||
не отменяются все таймеры; зафиксирован остаток 9 таймеров (665/656). В обработчиках
|
||||
трафика освобождается entry без queue_dgram_free. Нужна отдельная доработка fixture:
|
||||
владение таймерами и payload, backpressure отправителя, завершение deferred cleanup.
|
||||
Производственный auto_socket в рамках исправления приглашений не менялся.
|
||||
не отменялись все таймеры; зафиксирован остаток 9 таймеров (665/656). В обработчиках
|
||||
трафика освобождался entry без queue_dgram_free. Теперь у каждого таймера свой slot,
|
||||
waiters отменяются до teardown, payload освобождается, deferred cleanup завершается
|
||||
до проверки баланса таймеров, сокетов и `u_get_allocated_count()`.
|
||||
|
||||
Новый генератор шлёт 1024-байтовые пакеты независимо в обе стороны, по одному через
|
||||
threshold waiter, с бюджетом 64 пакета на tick. Проверяются содержимое, строгий seq,
|
||||
ограниченность TX/RX очередей, реальное срабатывание backpressure, остановка
|
||||
генераторов при полном обрыве и полное опустошение после восстановления. NCD handle
|
||||
удерживает логическую сессию: смена интерфейса не является разрешением терять её данные.
|
||||
Остатки после действительно удалённого соединения — отдельный допустимый случай.
|
||||
|
||||
Прогон нагрузки обнаружил ошибки, скрытые прежними проверками:
|
||||
|
||||
- `tcp_socket_add` не сохранял `netif_index`: монитор принимал interface-bound сокет
|
||||
за сокет default route и менял его адрес при событиях другого интерфейса.
|
||||
- Удаление TCP модели искало её по имени уже удалённого интерфейса и порту из БД.
|
||||
Теперь запись интерфейса хранит имя и прямую ссылку на модель; один путь закрывает
|
||||
listener, линки и модель. Портовые записи удаляются с сохранённым именем.
|
||||
- `tcp_socket_remove` не закрывал линки, созданные вне NCD. Теперь закрывает все
|
||||
связанные линки до освобождения модели; root-тест создаёт такой линк отдельно.
|
||||
- Поиск UDP модели не исключал TCP. Добавлена проверка типа сокета.
|
||||
- При selective ACK sender мог выдавать новые seq за границей `MAX_INFLIGHT_SIZE`
|
||||
относительно cumulative ACK. Теперь генерация seq останавливается на границе,
|
||||
cumulative ACK возобновляет очередь даже при отсутствии уже selectively-acked записей.
|
||||
Тесты проверяют блокировку, возобновление и uint32 wrap. ACK не может подтвердить
|
||||
ещё не назначенный seq; декодирование старшего байта seq/ACK не делает signed shift.
|
||||
- Timestamp Q16 умножался как signed int и переполнялся на циклических/отрицательных
|
||||
смещениях. Перевод выполняется в uint32. Jitter раньше всегда получал нулевую разницу:
|
||||
предыдущий RTT читался после перезаписи; теперь берётся до неё, EWMA использует int64.
|
||||
- UBSan выявил невыровненные canary/указатели в `mem.c` и `memory_pool.c`. Метаданные
|
||||
читаются/пишутся через memcpy; покрыты размеры блоков 1..17 и повторное использование пула.
|
||||
- Повторный общий прогон поймал `test_etcp_connect`: PID-порты пересекались с занятым
|
||||
UDP-портом (`EADDRINUSE`). Теперь сервер bind-ится на порт 0, клиент получает фактический
|
||||
порт через getsockname; собственного алгоритма поиска свободного порта нет.
|
||||
|
||||
Root ASan/UBSan/LSan: PASS, 153335 / 175912 пакетов, reinit=0, все очереди пусты,
|
||||
баланс памяти/таймеров/сокетов совпал (`/tmp/root-fix-asan.log`). Инструментированы
|
||||
тест, ETCP/session/router/NCD/autosocket/STCP/normalizer, очереди, event loop и аллокаторы;
|
||||
прочие объекты архивов обычные. Unit-логи: `/tmp/root-session-asan.log`,
|
||||
`/tmp/root-memory-asan.log`. LSan запускается вне sandbox: под ptrace он не работает.
|
||||
|
||||
Подробные socket/connection INFO включаются только через `UTUN_TEST_DEBUG=1`.
|
||||
`ENETUNREACH` непосредственно при принудительном удалении IP/интерфейса ожидаем до
|
||||
обработки netlink; тест требует последующей доставки всех данных. Ошибки выхода
|
||||
за receive window недопустимы и после исправления sender gate не наблюдаются.
|
||||
|
||||
## Попутная проблема диагностики
|
||||
|
||||
|
||||
@@ -41,6 +41,12 @@ inflight - две очереди (ll_queue):
|
||||
- send_hist[8] - история через какие линки отправлялся (индекс линка)
|
||||
- inflight_bytes/inflight_packets per-link отслеживается в ETCP_LINK
|
||||
Размер буфера inflight лимитируем как сумму по всем активным линкам optimal_inflight.
|
||||
Отдельно ограничиваем размах sequence относительно кумулятивного ACK: новый seq выдаётся
|
||||
только если (uint32_t)(next_tx_id - rx_ack_till) <= MAX_INFLIGHT_SIZE (16384).
|
||||
Selective ACK освобождает отдельную inflight-запись, но не продвигает эту границу:
|
||||
приёмник пока не может освободить пакеты за дыркой. Кумулятивный ACK возобновляет
|
||||
input_queue даже если подтверждённые записи уже удалены по selective ACK.
|
||||
ACK ограничивается последним назначенным seq (next_tx_id - 1); сравнения учитывают uint32 wrap.
|
||||
optimal_inflight расчитывается из RTT и bandwidth линка.
|
||||
|
||||
bandwidth по каждому линку адаптивно подстраиваем:
|
||||
|
||||
+7
-5
@@ -3,11 +3,13 @@
|
||||
Сюда пишется список задач с короткой аннотацией. Если задача большая и имеет ТЗ - то ТЗ оформляется отдельным файлом, а сюда помещается аннотация и ссылка на ТЗ.
|
||||
|
||||
## Текущая задача
|
||||
[ ] **test_auto_socket_dynamic: восстановить root-регрессию** — тест оставляет включённым
|
||||
фильтр default route для dummy-интерфейсов без default route и получает TIMEOUT.
|
||||
Исправить конфигурацию, владение таймерами (общий handle перезаписывается),
|
||||
освобождение payload, backpressure и очистку fixture. Root-прогон 2026-09-27:
|
||||
TIMEOUT, 9 оставшихся таймеров. [Разбор](etcp_full_suite_findings.md).
|
||||
[+] **test_auto_socket_dynamic: root-регрессия и нагрузка** — изолированный namespace,
|
||||
корректные маршруты, двусторонний поток через backpressure, строгие seq/payload,
|
||||
пределы TX/RX, остановка при обрыве и drain после восстановления, баланс ресурсов.
|
||||
Исправлены привязка TCP к интерфейсу, удаление TCP моделей/линков/портов из БД,
|
||||
sender receive window при selective ACK, timestamp overflow и нулевой jitter.
|
||||
ASan/UBSan/LSan: PASS; дополнительно исправлены невыровненные метки аллокаторов
|
||||
и PID-порты в test_etcp_connect. [Разбор и логи](etcp_full_suite_findings.md).
|
||||
|
||||
[ ] **debug_parse_config: формат и индексы категорий** — parser ожидает `:`, документация
|
||||
описывает `=`; преобразование битовой маски осталось после перехода enum на индексы.
|
||||
|
||||
Reference in new issue
Block a user