diff --git a/src/transport_layer/etcp.c b/src/transport_layer/etcp.c index 8dd1da07..3ff087f9 100644 --- a/src/transport_layer/etcp.c +++ b/src/transport_layer/etcp.c @@ -58,7 +58,7 @@ static void etcp_schedule_send(struct ETCP_CONN* conn, int delay_tb) { if (conn->tx_running && !delay_tb) return; int work = conn->input_send_q->count || conn->input_queue->count || conn->ack_till_pending || conn->ack_request_pending; for (struct ETCP_LINK* link = conn->links; !work && link; link = link->next) - work = link->burst_active || (link->ack_q && link->ack_q->count); + work = link->burst_active || link->ack_reply_pending || (link->ack_q && link->ack_q->count); if (!work) return; conn->tx_delayed = delay_tb != 0; conn->tx_token = delay_tb ? uasync_set_timeout(conn->instance->ua, delay_tb, conn, etcp_send_timer_cb, "etcp_tx") : @@ -1214,7 +1214,8 @@ struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* conn) { if (!link && packet) link = etcp_loadbalancer_select_link(conn, packet->ll.len, packet->last_attempt_id ? packet : NULL); if (!link) { for (struct ETCP_LINK* candidate = conn->links; candidate; candidate = candidate->next) - if (candidate->initialized && candidate->link_status && candidate->ack_q && candidate->ack_q->count) { + if (candidate->initialized && candidate->link_status && + (candidate->ack_reply_pending || (candidate->ack_q && candidate->ack_q->count))) { link = candidate; packet = NULL; break; } } @@ -1452,7 +1453,7 @@ void etcp_conn_input(struct ETCP_DGRAM* pkt) { break; } case ETCP_SECTION_ACK_REQUEST: - etcp->ack_till_pending = 1; etcp_conn_wake_sender(etcp); + pkt->link->ack_reply_pending = 1; etcp_conn_wake_sender(etcp); data++; len--; break; case ETCP_SECTION_TIMESTAMP: { diff --git a/src/transport_layer/etcp_connections.h b/src/transport_layer/etcp_connections.h index ef1055e2..870e6a99 100644 --- a/src/transport_layer/etcp_connections.h +++ b/src/transport_layer/etcp_connections.h @@ -252,6 +252,7 @@ struct ETCP_LINK { void* shaper_timer; struct ll_queue* attempts; // Физические попытки, индекс attempt_id:u64; ll.len учитывается в окне struct ll_queue* ack_q; // ACK только DATA этого линка, индекс attempt_id:u64 + uint8_t ack_reply_pending; // Ответ на запрос till возвращается тем же путём, даже при пустой ACK-очереди void* retrans_timer; // Срок старейшей принятой транспортом попытки этого канала uint64_t retrans_deadline_us; // Уже запланированная проверка: более ранний таймер можно сохранить uint32_t data_rtt_us; // Сглаженный RTT DATA->ACK этого пути; 0 до первого измерения diff --git a/src/transport_layer/etcp_tx.c b/src/transport_layer/etcp_tx.c index 4af39b53..ff6f5438 100644 --- a/src/transport_layer/etcp_tx.c +++ b/src/transport_layer/etcp_tx.c @@ -122,6 +122,7 @@ void etcp_tx_link_reset(struct ETCP_LINK* link, int retry) { link->shaper_load_time_tb = get_time_tb(); link->shaper_sub_nanotime = 0; link->bbr_pacing_rate = link->bandwidth = 0; link->data_rtt_us = link->data_jitter_us = link->bbr_loss_since_ack = 0; + link->ack_reply_pending = 0; link->delivered_bytes = link->acked_bytes = link->acked_packets = 0; link->last_ack_time_us = get_time_us(); link->first_tx_time_us = 0; link->cwnd_limited = 0; @@ -157,6 +158,7 @@ struct ETCP_TX_ATTEMPT* etcp_tx_prepare(struct ETCP_LINK* link, struct INFLIGHT_ void etcp_tx_complete(struct ETCP_DGRAM* dgram, int success) { if (success) { + dgram->link->ack_reply_pending = 0; dgram->link->etcp->ack_till_pending = 0; if (dgram->ack_request) dgram->link->etcp->ack_request_pending = 0; }