Define compact per-fragment ETCP attempt numbers

This commit is contained in:
evgeny committed 2026-10-23 19:19:07 +02:00
1 parent 8c3fcfd1c8
commit 6414cb15ef
3 files changed
+19 -12

No files matched your search

+4 -4
View File
@@ -77,7 +77,8 @@ struct INFLIGHT_PACKET {// выделяется из etcp->inflight_pool
uint32_t seq; // packet seq (ID по документации)
struct ETCP_LINK* last_link; // Заимствованный курсор выбора следующего пути; очищается перед free линка
uint64_t last_timestamp; // Время последней принятой отправки, 0.1мс; только диагностика, не RTO/BBR
uint64_t last_attempt_id; // Последняя принятая транспортом попытка; ненулевой ID отличает retry
uint64_t last_attempt_id; // Внутренний ключ последней принятой попытки (seq<<16)|номер; 0 — отправок не было
uint16_t attempt_count; // Выданные номера этого seq, 1..65535, общие для всех линков; исчерпание меняет эпоху
uint32_t send_count; // Статистика отправок с насыщением, без wrap
uint32_t retrans_req_count; // Число запросов повтора с насыщением
uint32_t active_attempts; // Попытки этого seq, ещё занимающие окна каналов
@@ -94,7 +95,7 @@ struct ETCP_FRAGMENT {// выделяется из пула etcp->rx_pool
struct ACK_PACKET {
struct ll_entry ll;
uint64_t attempt_id; // Индекс очереди конкретного линка
uint64_t attempt_id; // Внутренний индекс (seq<<16)|номер; по сети передаётся только номер u16
uint32_t seq; // Логический фрагмент
uint64_t received_at_us; // Полное локальное время, без modulo-wrap задержки
};
@@ -161,8 +162,7 @@ struct ETCP_CONN {
// IDs and state
uint32_t next_tx_id; // ID для добавления в очередь отправки (с этим id будет добавлен следующий пакет)
uint64_t next_attempt_id; // Не переиспользуется при reset/пересоздании линков; исчерпание закрывает соединение
uint32_t next_tx_id; // Следующий seq, 1..UINT32_MAX; перед повторным использованием нужна новая эпоха
uint32_t active_attempts; // Все физические записи, включая резерв send; максимум 2*MAX_INFLIGHT_SIZE
uint32_t last_rx_id; // Last received ID
uint32_t last_delivered_id; // Last delivered to output_queue
+4 -4
View File
@@ -37,8 +37,8 @@ extern "C" {
// Wire-MTU кап: пакет на проводе не должен превышать 1500 (согласовано с TUN_MAX_PACKET_SIZE).
// PACKET_DATA_SIZE (2048) — это внутренний буфер аллокации/приёма, а не wire-MTU.
#define PACKET_DATA_MAX_MTU 1500
#define ETCP_PAYLOAD_HEADER_SIZE 13 // type + seq:u32 + attempt_id:u64
#define ETCP_ACK_ENTRY_SIZE 16 // seq:u32 + attempt_id:u64 + receiver_delay_us:u32
#define ETCP_PAYLOAD_HEADER_SIZE 7 // type + seq:u32 + attempt_no:u16 (LE, 1..65535, общий номер для всех линков seq)
#define ETCP_ACK_ENTRY_SIZE 10 // seq:u32 + attempt_no:u16 + receiver_delay_us:u32; все числа LE
#define ETCP_MAX_PAYLOAD_SIZE (PACKET_DATA_SIZE - ETCP_ACK_BASE_SIZE - ETCP_PAYLOAD_HEADER_SIZE)
#define ETCP_RFC791_MIN_MTU 576
@@ -257,8 +257,8 @@ struct ETCP_LINK {
uint64_t shaper_sub_nanotime; // sub 0-999999 для 0.1 нс - 0.1 мс
uint8_t shaper_state;
void* shaper_timer;
struct ll_queue* attempts; // Физические попытки, индекс attempt_id:u64; ll.len учитывается в окне
struct ll_queue* ack_q; // ACK только DATA этого линка, индекс attempt_id:u64
struct ll_queue* attempts; // Физические попытки, внутренний ключ (seq<<16)|attempt_no; ll.len учитывается в окне
struct ll_queue* ack_q; // ACK только DATA этого линка, тот же составной ключ
uint8_t ack_reply_pending; // Ответ на запрос till возвращается тем же путём, даже при пустой ACK-очереди
void* retrans_timer; // Срок старейшей принятой транспортом попытки этого канала
uint64_t retrans_deadline_us; // Уже запланированная проверка: более ранний таймер можно сохранить
+11 -4
View File
@@ -14,10 +14,15 @@ struct ETCP_LINK;
struct ETCP_DGRAM;
struct INFLIGHT_PACKET;
/* Запись из attempt_pool соединения; индекс очереди линка — attempt_id, payload здесь не хранится. */
/* Внутренний ключ пары seq/номер без padding. Номер 1..65535; wire содержит seq:u32 и номер:u16 отдельно. */
static inline uint64_t etcp_tx_attempt_id(uint32_t seq, uint16_t number) {
return ((uint64_t)seq << 16) | number;
}
/* Запись из attempt_pool соединения; индекс очереди линка — составной attempt_id, payload здесь не хранится. */
struct ETCP_TX_ATTEMPT {
struct ll_entry ll; // len — DATA-байты, dgram=NULL; одна очередь, владелец — линк
uint64_t attempt_id; // уникален в пределах жизни соединения, 0 не используется
uint64_t attempt_id; // (seq<<16)|номер; пара не повторяется в одной эпохе, младшие 16 бит ненулевые
uint32_t seq; // логический фрагмент; может быть уже освобождён после доставки
uint64_t sent_at_us; // время принятия транспортом; 0 — пока зарезервирован
uint64_t delivered_at_send; // доставленные DATA-байты этого канала на момент отправки
@@ -40,12 +45,14 @@ void etcp_tx_link_destroy(struct ETCP_LINK* link);
uint32_t etcp_tx_rto_us(const struct ETCP_LINK* link);
/* Резервировать окно для packet; NULL — ошибка с логом, packet остаётся в очереди отправки.
* Физические записи ограничены MAX_INFLIGHT_SIZE на линк и 2*MAX_INFLIGHT_SIZE на соединение.
* Исчерпание бюджета блокирует выбор DATA до ACK/RTO/закрытия; ACK-очередь линка ограничена MAX_INFLIGHT_SIZE. */
* Исчерпание бюджета блокирует выбор DATA до ACK/RTO/закрытия; ACK-очередь линка ограничена MAX_INFLIGHT_SIZE.
* Номер общий для всех линков одного seq; выданный номер не возвращается при отказе send.
* После номера 65535 новый prepare сбрасывает поток со сменой эпохи, не оборачивает счётчик. */
struct ETCP_TX_ATTEMPT* etcp_tx_prepare(struct ETCP_LINK* link, struct INFLIGHT_PACKET* packet);
/* Завершить синхронный send: success=1 принят транспортом, 0 — снять резерв без сетевой потери.
* Вызвать ровно один раз до освобождения dgram и до следующего poll; dgram->attempt обнуляется. */
void etcp_tx_complete(struct ETCP_DGRAM* dgram, int success);
/* Принятый ACK: seq подтверждает логическую доставку; attempt_id обновляет окно/BBR только своего линка.
/* Принятый ACK: seq подтверждает логическую доставку; внутренний attempt_id=(seq<<16)|номер обновляет только свой линк.
* Неизвестный старый ID не создаёт измерение и не вычитает окно. UINT32_MAX delay — RTT недостоверен.
* peer_rx_bytes/time_us — согласованная точка приёма пути из ACK; 0/0 — неизвестна.
* Достоверная пара ограничивает BW темпом приёма, сохраняя границы send/ACK; RTT и доставка от неё не зависят.