Recover DATA RTT sampling after path delay increases

This commit is contained in:
evgeny committed 2026-10-24 17:26:59 +02:00
1 parent dbda8a24d7
commit ef404da44c
3 files changed
+29 -6

No files matched your search

+4 -3
View File
@@ -16,7 +16,8 @@ static struct INFLIGHT_PACKET* logical_find(struct ETCP_CONN* conn, uint32_t seq
}
uint32_t etcp_tx_rto_us(const struct ETCP_LINK* link) {
uint64_t rtt = link->data_rtt_us ? link->data_rtt_us : (uint64_t)link->rtt_last * 100;
uint64_t rtt = link->data_rtt_us;
if ((uint64_t)link->rtt_last * 100 > rtt) rtt = (uint64_t)link->rtt_last * 100;
uint64_t rto = rtt ? (12 * rtt + 15ULL * link->data_jitter_us + 9) / 10 + 3000 : 1000000;
if (rto < 10000) rto = 10000;
if (rto > 1000000) rto = 1000000;
@@ -101,9 +102,9 @@ static void retransmit_cb(void* arg) {
while (link->attempts->head) {
struct ETCP_TX_ATTEMPT* attempt = (struct ETCP_TX_ATTEMPT*)link->attempts->head;
if (!attempt->sent_at_us || now - attempt->sent_at_us < rto) break;
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] RTO link=%u attempt=%u seq=%u age_us=%llu RTO_us=%u RTT_us=%u jitter_us=%u",
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] RTO link=%u attempt=%u seq=%u age_us=%llu RTO_us=%u DATA_RTT_us=%u KA_RTT_us=%u jitter_us=%u",
link->etcp->log_name, link->local_link_id, (unsigned)(uint16_t)attempt->attempt_id, attempt->seq,
(unsigned long long)(now - attempt->sent_at_us), rto, link->data_rtt_us, link->data_jitter_us);
(unsigned long long)(now - attempt->sent_at_us), rto, link->data_rtt_us, link->rtt_last * 100, link->data_jitter_us);
attempt_retire(link, attempt, 1, 1);
}
retransmit_arm(link);
+3 -1
View File
@@ -43,7 +43,9 @@ int etcp_tx_link_init(struct ETCP_LINK* link);
void etcp_tx_link_reset(struct ETCP_LINK* link, int retry);
void etcp_tx_link_destroy(struct ETCP_LINK* link);
/* RTO = clamp(ceil(1.2*RTT + 1.5*jitter + 3000), 10000, 1000000), все величины в мкс.
* RTT/jitter — собственные DATA-измерения линка; до DATA ACK использует KA RTT, без RTT — 1с. */
* RTT=max(DATA EWMA, последний RTT timestamp/keepalive) своего линка; jitter — только DATA, без RTT — 1с.
* Timestamp-RTT задаёт нижнюю границу, чтобы рост задержки не удалял все попытки до их ACK и не замораживал DATA-измерения.
* Это граница RTO; RTT/min_rtt и BW модели BBR по-прежнему обновляет только ACK действующей DATA-попытки. */
uint32_t etcp_tx_rto_us(const struct ETCP_LINK* link);
/* Резервировать окно для packet; NULL — отказ с логом. OOM/бюджет сохраняют packet в очереди,
* исчерпание номера меняет эпоху и удаляет прежний поток, включая packet.
+22 -2
View File
@@ -374,7 +374,9 @@ static void retransmission_timeout(void) {
{600000, 100000, 0, 873000}, {1000000, 0, 0, 1000000}, {UINT32_MAX, UINT32_MAX, 0, 1000000},
{5833, 0, 0, 10000}, {5834, 0, 0, 10001}, {20001, 1, 0, 27003},
{20000, 10000, 0, 42000}, {200000, 100000, 0, 393000},
{0, 0, 200, 27000}, {20000, 0, 6000, 27000}, {0, 0, UINT16_MAX, 1000000},
{0, 0, 200, 27000}, {20000, 0, 6000, 723000}, {0, 0, UINT16_MAX, 1000000},
{20000, 0, 1000, 123000}, {20000, 7500, 1000, 134250},
{200000, 0, 200, 243000}, {20000, 0, 1, 27000}, {20000, 0, UINT16_MAX, 1000000},
{830832, 0, 0, 999999}, {830833, 0, 0, 1000000}, {830834, 0, 0, 1000000}
};
for (unsigned i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
@@ -747,6 +749,24 @@ static void enable_models(void) {
}
}
/* Скачок RTT не уничтожает попытку до прихода ACK; уже назначенный ранний таймер проверяет новый RTO. */
static void rto_path_rtt_growth(void) {
setup(); enable_models(); b->link_status = 0;
a->data_rtt_us = 20000; a->rtt_last = 200;
fill(a,1,1000);
struct INFLIGHT_PACKET* packet = (struct INFLIGHT_PACKET*)conn->input_wait_ack->head;
uint32_t seq = packet->seq; uint64_t id = packet->last_attempt_id;
a->rtt_last = 1000;
test_clock_run_for(ua,1000);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "RTO after path RTT growth: DATA_us=%u KA_us=%u RTO_us=%u attempts=%u retries=%u stalled=%u",
a->data_rtt_us,a->rtt_last*100,etcp_tx_rto_us(a),a->inflight_packets,conn->retransmissions_count,a->tx_stalled);
CHECK(queue_find_data_by_index(a->attempts,&id) && !conn->retransmissions_count && !a->tx_stalled);
etcp_tx_ack(a,seq,id,0,0,0);
CHECK(a->data_rtt_us > 20000 && bbr_calls == 1 && last_sample.rtt_us >= 100000);
CHECK(a->acked_packets == 1 && !a->inflight_bytes && !conn->unacked_bytes);
teardown();
}
static void receive_till(struct ETCP_LINK* link, uint32_t till, int query) {
struct ETCP_DGRAM* pkt = memory_pool_alloc(inst.pkt_pool); CHECK(pkt);
pkt->link = link; pkt->data_len = ETCP_ACK_BASE_SIZE + query;
@@ -1752,7 +1772,7 @@ int main(void) {
void (*cases[])(void) = {selection, boundaries_ack_burst, late_ack_and_migration, lost_ack_and_shrink,
grow_and_session, allocation_and_send_failure, removed_link_and_bbr, pacing_reset_close, initial_readiness,
config_limits, timer_failure, immediate_send, ack_without_data_pacing, bbr_delivery_clock, bbr_probe_window, tcp_initial_window,
retransmission_timeout, pacing_rate_changes, pacing_timer_failure, retry_rotation, independent_attempt_acks,
rto_path_rtt_growth, retransmission_timeout, pacing_rate_changes, pacing_timer_failure, retry_rotation, independent_attempt_acks,
retry_waits_for_alternative, retry_alternative_lifecycle,
send_queue_scan, send_queue_input_admission,
retry_full_round_history, retry_history_slot_reuse, fast_stall_progress, stalled_retry_selection, input_admission_callbacks,