Document send scanning, retry rounds, and fast stall recovery
This commit is contained in:
1 parent
93bf846fc4
commit
34d1dcb7c8
3 files changed
+29
-12
No files matched your search
+21
-7
@@ -9,26 +9,35 @@ close/reset отменяет ожидающий запуск. Не подтве
|
||||
HELLO/CHALLENGE/CONFIRM и keepalive передаются своим независимым путём.
|
||||
|
||||
Формирование пакета:
|
||||
1. Посмотреть следующий DATA и его длину, не извлекая его из input_send_q.
|
||||
1. Просмотреть input_send_q без извлечения: первый готовый повтор, иначе первый готовый новый DATA.
|
||||
Заблокированная запись пропускается; порядок остальных записей не меняется. Поиск не резервирует окно,
|
||||
не выдаёт номер попытки и не меняет историю/RR. Если кандидата нет, можно подгрузить один новый фрагмент
|
||||
и повторить просмотр. Общий бюджет учитывает DATA-байты send_q+wait_ack; приёмное окно по till сохраняется.
|
||||
После callback подгрузки проверяются reset_count/close/сессия, включая удаление прежнего burst-линка.
|
||||
2. Выбрать инициализированный UP-линк с готовым shaper и местом для целого DATA:
|
||||
inflight_bytes + длина DATA <= inflight_lim_bytes. Проверка выполняется без переполнения.
|
||||
Среди допустимых выбирается минимум inflight_bytes, при равенстве — round-robin.
|
||||
Для повтора обход начинается после last_link самого фрагмента: первый готовый другой канал.
|
||||
Пока существует другой initialized+UP канал, прежний не используется: занятость альтернатив
|
||||
по cwnd/pacing означает ожидание их события без создания новой попытки/RTO.
|
||||
Прежний канал разрешён только при отсутствии таких альтернатив; DOWN последней альтернативы
|
||||
пробуждает отправителя. Чужие DATA/ACK не меняют курсор фрагмента; удаление линка обнуляет его до free.
|
||||
Для повтора обход начинается после last_link самого фрагмента: сначала неиспользованные допустимые пути.
|
||||
История — битовая карта256 локальных слотов,32 байта на логический пакет; wire-формат не меняется.
|
||||
Пока остался неиспользованный путь, занятый по cwnd/pacing, этот пакет ждёт, а send_q просматривается дальше.
|
||||
Когда все допустимые пути использованы, разрешён следующий обход. Очистка истории и новый бит фиксируются
|
||||
только после принятия send; отказ send не расходует обход. Перед удалением линка очищаются его курсор/бит
|
||||
во всех логических записях до освобождения слота и callbacks, которые могут повторно выдать тот же local_link_id.
|
||||
При наличии незастрявшего initialized+UP пути застрявшие исключены из повторов, даже если альтернатива занята.
|
||||
Если застряли все, доступны все UP-пути. Прежний путь разрешён лишь при отсутствии других допустимых;
|
||||
иначе ждём альтернативу. DOWN последней альтернативы пробуждает отправителя.
|
||||
3. Если DATA не помещается, он остаётся в очереди; для накопленных ACK выбирается
|
||||
тот же линк, который принял соответствующий DATA, без ограничения DATA-cwnd/pacing.
|
||||
Кумулятивный till можно отправить по любому рабочему пути. ACK-only не увеличивает нагрузку DATA-shaper;
|
||||
физическая очередь канала остаётся общей, её накопление ограничивают DATA-cwnd/pacing BBR.
|
||||
4. Выделить ETCP_DGRAM до удаления DATA из очереди и изменения счётчиков.
|
||||
Выделить физическую попытку с новым attempt_no для этого seq и зарезервировать окно выбранного линка.
|
||||
Только успешное принятие транспортом фиксирует время, last_link и перенос DATA в input_wait_ack.
|
||||
Только успешное принятие транспортом фиксирует время, last_link, историю/RR и перенос DATA в input_wait_ack.
|
||||
Ошибка send снимает резерв; логический DATA остаётся готовым без сетевого loss sample.
|
||||
Пакет содержит ACK, опциональные timestamp/измерительные секции и последнюю секцию PAYLOAD.
|
||||
5. В активной ограниченной burst-серии pacing обходится; DATA всё равно должен
|
||||
помещаться в окно, иначе серия отправляет FILLER. ACK/FILLER окно DATA не занимают.
|
||||
Если готовый повтор относится к другому пути, серия идёт FILLER: новые DATA его не обгоняют.
|
||||
При приёме пакета (от etcp_connections):
|
||||
- последовательно сканируем секции и отдаём их на обработку нужным обработчикам:
|
||||
- ack (0x01): пара seq+attempt_no подтверждает физическую попытку только принявшего ACK линка;
|
||||
@@ -113,6 +122,11 @@ Shaper списывает только DATA-байты: единицы совп
|
||||
не должно скрывать этот факт от BBR. app_limited учитывает ожидающие очереди и
|
||||
pending/частичный буфер normalizer; ограничение окном не означает отсутствие данных.
|
||||
Потеря для BBR учитывается при RTO, фактическая повторная передача — при новой попытке.
|
||||
Три RTO физических DATA-попыток без ACK-прогресса ставят локальный флаг tx_stalled, в том числе в одном вызове таймера.
|
||||
До установки флага действующий ACK своего пути сбрасывает серию RTO. После установки сброс возможен только по ACK
|
||||
попытки, принятой транспортом после момента установки флага; старый/чужой/уже снятый attempt не доказывает восстановление.
|
||||
tx_stalled ограничивает выбор повторов при наличии альтернативы; UP, новые DATA, ACK/keepalive и формула RTO сохраняются.
|
||||
Reset линка снимает флаг и серию RTO. Новых очередей, копий payload и таймеров детектор не создаёт.
|
||||
При уменьшении окна уже отправленные пакеты остаются в учёте; новые DATA ждут ACK/RTO.
|
||||
Измерительные секции burst 0x07/0x08 и FILLER поддерживаются реализацией.
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ struct ETCP_CONN {
|
||||
struct memory_pool* attempt_pool; // метаданные физических попыток; payload принадлежат inflight_pool
|
||||
struct memory_pool* io_pool; // память для rx очередей
|
||||
|
||||
struct ll_queue* input_send_q; // очередь на отправку (inflight_pool -> INFLIGHT_PACKET)
|
||||
struct ll_queue* input_send_q; // новые DATA/повторы; выбирается готовый повтор либо готовый новый пакет, не только голова
|
||||
struct ll_queue* input_wait_ack; // очередь ожидающих подтверждение (inflight_pool -> struct INFLIGHT_PACKET)
|
||||
|
||||
struct ll_queue* recv_q; // очередь на сборку фрагментированных пакетов(rx_pool -> struct ETCP_FRAGMENT) + index [+0 SEQ]
|
||||
@@ -192,9 +192,9 @@ struct ETCP_CONN {
|
||||
// uint32_t bytes_sent_norx; // сколько отправили байт без единого ответного пакета (для детекции запроса реконнекта)
|
||||
|
||||
// Window and inflight management
|
||||
uint32_t unacked_bytes; // Current inflight bytes
|
||||
uint32_t unacked_bytes; // логические DATA-байты input_send_q + input_wait_ack; не физический flight копий
|
||||
uint32_t max_inflight; // Max inflight cap from config (bbr_max_cwnd)
|
||||
uint32_t optimal_inflight; // Sum over links
|
||||
uint32_t optimal_inflight; // сумма индивидуальных окон; общий бюджет подгрузки новых DATA с учётом unacked_bytes
|
||||
|
||||
// Timers
|
||||
void* ack_resp_timer; // ACK send timer
|
||||
@@ -341,7 +341,10 @@ void etcp_conn_input(struct ETCP_DGRAM* pkt);
|
||||
// Returns: 0 on success, -1 on failure
|
||||
int etcp_int_send(struct ETCP_CONN* etcp, const void* data, uint16_t len);
|
||||
|
||||
// Request next packet for load balancer
|
||||
/* Подготовить следующий пакет из pkt_pool либо NULL при ожидании/ошибке/отсутствии работы.
|
||||
* Сканирует send_q: готовые повторы имеют приоритет, заблокированные записи пропускаются.
|
||||
* При отсутствии кандидата допускает одну подгрузку в рамках общего/приёмного окна; callback может сделать reset/close.
|
||||
* Пакет с DATA содержит резерв попытки: etcp_loadbalancer_send завершает send/rollback и возвращает пакет в пул. */
|
||||
struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* etcp);
|
||||
|
||||
/* Запросить один отложенный проход отправителя; не меняет UP/DOWN. Все вызовы — в uasync.
|
||||
|
||||
@@ -58,7 +58,7 @@ struct ETCP_TX_ATTEMPT* etcp_tx_prepare(struct ETCP_LINK* link, struct INFLIGHT_
|
||||
void etcp_tx_complete(struct ETCP_DGRAM* dgram, int success);
|
||||
/* Принятый ACK: seq подтверждает логическую доставку; внутренний attempt_id=(seq<<16)|номер обновляет только свой линк.
|
||||
* Неизвестный старый ID не создаёт измерение и не вычитает окно. UINT32_MAX delay — RTT недостоверен.
|
||||
* Действующий ACK сбрасывает серию RTO; флаг застревания снимается только для отправки после его установки.
|
||||
* До застревания действующий ACK сбрасывает серию RTO; после — только ACK отправки после установки флага сбрасывает серию/флаг.
|
||||
* peer_rx_bytes/time_us — согласованная точка приёма пути из ACK; 0/0 — неизвестна.
|
||||
* Достоверная пара ограничивает BW темпом приёма, сохраняя границы send/ACK; RTT и доставка от неё не зависят.
|
||||
* interval=max(send_us,ack_us,ceil(delivered*delta_rx_us/delta_rx_bytes)); дельты от снимка при отправке.
|
||||
|
||||
Reference in new issue
Block a user