From 1c18bdc9abbcbabd2c2f7fb70fe1479555e7f079 Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 23 Oct 2026 00:06:30 +0200 Subject: [PATCH] Measure BBR delivery over packet flights instead of inter-ACK gaps --- src/transport_layer/etcp.c | 22 +++++++++++++++++----- src/transport_layer/etcp_bbr.c | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/transport_layer/etcp.c b/src/transport_layer/etcp.c index e6379827..77f0326c 100644 --- a/src/transport_layer/etcp.c +++ b/src/transport_layer/etcp.c @@ -679,6 +679,7 @@ void etcp_conn_reset(struct ETCP_CONN* etcp) { l->acked_bytes = 0; l->acked_packets = 0; l->last_ack_time_tb = get_time_tb(); + l->first_tx_time_tb = 0; l = l->next; } @@ -1304,12 +1305,16 @@ struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* etcp) { inf_pkt->last_link->total_retransmissions++; } + // Новый flight не включает время простоя в оценку скорости. + if (!link->inflight_packets) { link->first_tx_time_tb = now; link->last_ack_time_tb = now; } // Always add to the CURRENT link (first send or retransmission) link->inflight_bytes += inf_pkt->ll.len; link->inflight_packets++; // BBR: сохраняем снэпшот на момент отправки inf_pkt->delivered_at_send = link->delivered_bytes; + inf_pkt->delivered_time_at_send_tb = link->last_ack_time_tb; + inf_pkt->first_tx_at_send_tb = link->first_tx_time_tb; inf_pkt->inflight_at_send = link->inflight_bytes; struct PKTNORM* pn = etcp->normalizer; inf_pkt->is_app_limited = !etcp->input_queue->count && !etcp->input_send_q->count && @@ -1599,9 +1604,15 @@ void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq, uint16_t ts, uint16_t d // BBR: собираем rate_sample и вызываем bbr_main uint64_t now_tb = get_time_tb(); - uint32_t interval_us = link->last_ack_time_tb ? (uint32_t)((now_tb - link->last_ack_time_tb) * 100) : 0; + link->delivered_bytes += acked_pkt->ll.len; + uint64_t delivered = link->delivered_bytes - acked_pkt->delivered_at_send; + uint64_t ack_elapsed = now_tb - acked_pkt->delivered_time_at_send_tb; + uint64_t send_elapsed = acked_pkt->last_timestamp - acked_pkt->first_tx_at_send_tb; + uint64_t interval = (ack_elapsed > send_elapsed ? ack_elapsed : send_elapsed) * 100; + uint32_t interval_us = interval > UINT32_MAX ? UINT32_MAX : (uint32_t)interval; + if (acked_pkt->state == INFLIGHT_STATE_WAIT_SEND) interval_us = 0; // поздний ACK до retry, timestamp уже заменён RTO struct bbr_rate_sample rs = { - .delivered = acked_pkt->ll.len, + .delivered = delivered > UINT32_MAX ? UINT32_MAX : (uint32_t)delivered, .interval_us = interval_us, .rtt_us = (uint32_t)link->rtt_last * 100, .acked_sacked = acked_pkt->ll.len, @@ -1610,11 +1621,12 @@ void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq, uint16_t ts, uint16_t d .lost = (int)link->bbr_loss_since_ack, .is_app_limited = acked_pkt->is_app_limited, }; - link->delivered_bytes += rs.delivered; link->last_ack_time_tb = now_tb; + if (acked_pkt->state == INFLIGHT_STATE_WAIT_ACK && acked_pkt->last_timestamp > link->first_tx_time_tb) + link->first_tx_time_tb = acked_pkt->last_timestamp; - DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[L%u] BBR in: seq=%u del=%u iv=%uus rtt=%uus pri=%u tx_infl=%u cur=%u/%u lost=%d app=%d", - link->local_link_id, seq, rs.delivered, rs.interval_us, rs.rtt_us, + DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[L%u] BBR in: seq=%u del=%u acked=%u iv=%uus rtt=%uus pri=%u tx_infl=%u cur=%u/%u lost=%d app=%d", + link->local_link_id, seq, rs.delivered, rs.acked_sacked, rs.interval_us, rs.rtt_us, rs.prior_delivered, rs.tx_in_flight, link->inflight_bytes, link->inflight_lim_bytes, rs.lost, rs.is_app_limited); diff --git a/src/transport_layer/etcp_bbr.c b/src/transport_layer/etcp_bbr.c index 36aa67ac..f6908d82 100644 --- a/src/transport_layer/etcp_bbr.c +++ b/src/transport_layer/etcp_bbr.c @@ -885,7 +885,7 @@ void bbr_main(struct bbr* bbr, const struct bbr_rate_sample* rs, uint32_t sample_bw, bw; int update_model = 1; - bbr->delivered += rs->delivered; + bbr->delivered += rs->acked_sacked; bbr_update_round_start(bbr, rs); if (bbr->round_start)