Serve due path ACKs before DATA on another link
This commit is contained in:
1 parent
73096e8e3e
commit
72d7405a97
2 files changed
+31
-8
No files matched your search
@@ -1144,14 +1144,23 @@ struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* conn) {
|
||||
conn->session_required || conn->reinit_pending) return NULL;
|
||||
if (pulled) packet = send_queue_select(conn, &link);
|
||||
}
|
||||
if (!link) {
|
||||
if (!link || !link->burst_active) {
|
||||
uint64_t now = get_time_us();
|
||||
for (struct ETCP_LINK* candidate = conn->links; candidate; candidate = candidate->next)
|
||||
if (candidate->initialized && candidate->link_status &&
|
||||
(candidate->ack_reply_pending || (candidate->ack_q && candidate->ack_q->head &&
|
||||
now >= ((struct ACK_PACKET*)candidate->ack_q->head)->received_at_us + ETCP_ACK_DELAY_US))) {
|
||||
link = candidate; packet = NULL; break;
|
||||
}
|
||||
struct ETCP_LINK* ack_link = NULL;
|
||||
uint64_t first_due = UINT64_MAX;
|
||||
for (struct ETCP_LINK* candidate = conn->links; candidate; candidate = candidate->next) {
|
||||
if (!candidate->initialized || !candidate->link_status) continue;
|
||||
const struct ACK_PACKET* first = candidate->ack_q ? (struct ACK_PACKET*)candidate->ack_q->head : NULL;
|
||||
if (!candidate->ack_reply_pending && !first) continue;
|
||||
uint64_t due = candidate->ack_reply_pending ? 0 : first->received_at_us + ETCP_ACK_DELAY_US;
|
||||
if (due <= now && (!ack_link || due < first_due)) { ack_link = candidate; first_due = due; }
|
||||
}
|
||||
if (ack_link) {
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "[%s] ACK due path=%u deadline_us=%llu now_us=%llu piggyback=%u", conn->log_name,
|
||||
ack_link->local_link_id, (unsigned long long)first_due, (unsigned long long)now, ack_link == link && packet != NULL);
|
||||
if (ack_link != link) packet = NULL;
|
||||
link = ack_link;
|
||||
}
|
||||
}
|
||||
if (!link && (conn->ack_request_pending ||
|
||||
(conn->ack_till_deadline_us && conn->ack_till_deadline_us <= get_time_us()))) {
|
||||
|
||||
@@ -1286,6 +1286,20 @@ static void ack_link_lifecycle(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Готовый DATA другого пути не должен обходить уже наступивший срок ACK. */
|
||||
static void ack_due_other_link(void) {
|
||||
setup(); conn->got_initial_pkt = 1;
|
||||
ack_now_us = get_time_us(); ack_clock_active = 1;
|
||||
receive_fragment(b, 2, 1); b->inflight_lim_bytes = 1;
|
||||
ack_now_us += ETCP_ACK_DELAY_US;
|
||||
struct INFLIGHT_PACKET* fresh = enqueue(100);
|
||||
struct ETCP_DGRAM* pkt = request();
|
||||
CHECK(pkt && pkt->link == b && !pkt->payload_len && pkt->data[1] == 1 && fresh->state == INFLIGHT_STATE_WAIT_SEND);
|
||||
memory_pool_free(inst.pkt_pool, pkt);
|
||||
pkt = request(); CHECK(pkt && pkt->link == a && pkt->payload_len == 100);
|
||||
memory_pool_free(inst.pkt_pool, pkt); ack_all(); teardown();
|
||||
}
|
||||
|
||||
static void receive_admission_and_path_acks(void) {
|
||||
setup(); conn->got_initial_pkt = 1;
|
||||
fail_rx_data = 1; receive_fragment(a, 2, 1);
|
||||
@@ -1712,7 +1726,7 @@ int main(void) {
|
||||
send_queue_scan, send_queue_input_admission,
|
||||
retry_full_round_history, retry_history_slot_reuse, fast_stall_progress, stalled_retry_selection, input_admission_callbacks,
|
||||
ack_absolute_deadline, ack_piggyback_deadlines, ack_partial_piggyback, ack_timer_interleaving,
|
||||
ack_urgent_and_oom, ack_partial_frame_and_lifecycle, ack_sender_failure, ack_link_lifecycle,
|
||||
ack_urgent_and_oom, ack_partial_frame_and_lifecycle, ack_sender_failure, ack_link_lifecycle, ack_due_other_link,
|
||||
receive_admission_and_path_acks, peer_window_queries, pacing_continuity, pacing_data_units, attempt_memory_limits,
|
||||
normalizer_rx_oom, normalizer_tx_oom, normalizer_callback_abort, reset_without_allocation, restart_allocation_failures,
|
||||
receiver_bandwidth_bounds, receiver_point_lifecycle, receiver_point_wire, receiver_point_truncated,
|
||||
|
||||
Reference in new issue
Block a user