diff --git a/src/transport_layer/etcp.h b/src/transport_layer/etcp.h index 92b28dd0..55b46209 100644 --- a/src/transport_layer/etcp.h +++ b/src/transport_layer/etcp.h @@ -66,6 +66,7 @@ uint16_t get_current_timestamp(void); #define INFLIGHT_STATE_WAIT_SEND 1 #define INFLIGHT_INITIAL_HASH_SIZE 1024 #define ETCP_LINK_HISTORY_BYTES 32 // по одному биту для локального слота линка 0..255 +#define ETCP_ACK_DELAY_US 2000 // обычный ACK-only: срок от старейшей записи; piggyback и срочный ответ не ждут #define MAX_INFLIGHT_SIZE 16384 // максимальное число элементов в inflight приёмной очереди (для предотвращения атак) #define ETCP_ACK_GAP_MAX_PACKETS 8192 // предел кумулятивного ACK за приём: 8192 × PACKET_DATA_SIZE(2048) = 16 MB (защита от DoS) @@ -197,9 +198,10 @@ struct ETCP_CONN { uint32_t optimal_inflight; // сумма индивидуальных окон; общий бюджет подгрузки новых DATA с учётом unacked_bytes // Timers - void* ack_resp_timer; // ACK send timer + void* ack_resp_timer; // один таймер ближайшего срока ACK всех линков/логической границы + uint64_t ack_resp_deadline_us; // абсолютный срок установленного таймера; 0 без таймера void* ack_window_timer; // запрос потерянного till, только при заполненном приёмном окне - uint8_t ack_till_pending; // нужно передать текущую логическую границу по рабочему пути + uint64_t ack_till_deadline_us; // срок передачи текущей логической границы по рабочему пути; 0 — нет запроса uint8_t ack_request_pending; // нужно запросить границу у пира void* down_timer; // удаление после непрерывного DOWN, включая первоначальное ожидание uint64_t down_deadline_tb; // сохраняется при наличии NCD handles после истечения таймера @@ -351,6 +353,11 @@ struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* etcp); * Используется очередями, ACK/RTO, изменением окна и подтверждением сессии. close/reset отменяет запуск. */ void etcp_conn_wake_sender(struct ETCP_CONN* conn); +/* Пересчитать единственный ACK-таймер по головам очередей и ack_till_deadline_us; просроченную работу передать sender. + * Вызвать после RX/продвижения till, завершения send и смены доступных путей. NULL/закрытый conn допустимы. + * Piggyback не ждёт сроков. При OOM таймера существующие флаги срочного ACK обеспечивают немедленный fallback. */ +void etcp_conn_schedule_ack(struct ETCP_CONN* conn); + // Process ACK receipt - remove acknowledged packet from inflight queues void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq); diff --git a/src/transport_layer/etcp_connections.h b/src/transport_layer/etcp_connections.h index 47b8fa20..6843985b 100644 --- a/src/transport_layer/etcp_connections.h +++ b/src/transport_layer/etcp_connections.h @@ -264,7 +264,7 @@ struct ETCP_LINK { void* shaper_timer; struct ll_queue* attempts; // Физические попытки, внутренний ключ (seq<<16)|attempt_no; ll.len учитывается в окне struct ll_queue* ack_q; // ACK только DATA этого линка, тот же составной ключ - uint8_t ack_reply_pending; // Ответ на запрос till возвращается тем же путём, даже при пустой ACK-очереди + uint8_t ack_reply_pending; // срочный ACK: ответ till тем же путём либо fallback при OOM таймера; обходит ACK_DELAY void* retrans_timer; // Срок старейшей принятой транспортом попытки этого канала uint64_t retrans_deadline_us; // Уже запланированная проверка: более ранний таймер можно сохранить uint32_t data_rtt_us; // Сглаженный RTT DATA->ACK этого пути; 0 до первого измерения