Exercise RTT changes through real ETCP and document RTO inputs
This commit is contained in:
1 parent
ef404da44c
commit
68a225baec
3 files changed
+50
-2
No files matched your search
@@ -51,10 +51,13 @@ HELLO/CHALLENGE/CONFIRM и keepalive передаются своим незав
|
||||
после сканирования проверяем появились ли в linked-list собранные данные которые можно переместить в выходную очередь. и перемещаем если есть.
|
||||
|
||||
Таймер попыток каждого линка (etcp_tx.c):
|
||||
- RTO = clamp(ceil(1.2*data_rtt_us + 1.5*data_jitter_us + 3000), 10000, 1000000) мкс.
|
||||
- RTO = clamp(ceil(1.2*RTT_for_RTO + 1.5*data_jitter_us + 3000), 10000, 1000000) мкс,
|
||||
RTT_for_RTO=max(data_rtt_us,100*rtt_last): DATA EWMA и последний timestamp/keepalive RTT своего линка.
|
||||
Целочисленный расчёт использует uint64 и округляет вверх до целой микросекунды.
|
||||
RTT использует собственный DATA ACK минус receiver_delay; EWMA RTT=1/8, jitter=1/4 |RTT-EWMA|.
|
||||
Первый RTT задаёт jitter=RTT/2. До DATA ACK используется RTT keepalive этого же пути, без него RTO=1с.
|
||||
Первый DATA RTT задаёт jitter=RTT/2. Timestamp-RTT задаёт нижнюю границу срока, чтобы после роста задержки
|
||||
попытки доживали до ACK и DATA-измерения продолжались; BBR RTT/min_rtt по этому сигналу не обновляются.
|
||||
Без обоих измерений RTO=1с.
|
||||
- FIFO содержит физические попытки в порядке принятия транспортом. Таймер назначается по старейшей;
|
||||
при изменении RTO проверяется новый срок. Допускается оставить уже запланированную более раннюю проверку.
|
||||
uasync округляет задержку вверх до миллисекунды; callback может выполниться позже расчётного срока.
|
||||
|
||||
@@ -521,6 +521,7 @@ static int test_startup_delay_exit(void) {
|
||||
int main(void)
|
||||
{
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); debug_set_category_level(DEBUG_CATEGORY_DEBUG, DEBUG_LEVEL_INFO);
|
||||
if (getenv("UTUN_TEST_DEBUG")) debug_set_category_level(DEBUG_CATEGORY_ETCP, DEBUG_LEVEL_DEBUG);
|
||||
test_byte_rate();
|
||||
test_large_rate();
|
||||
test_probe_growth_bytes();
|
||||
|
||||
@@ -818,6 +818,46 @@ static void stalled(const struct profile* settings, unsigned count, unsigned bro
|
||||
teardown();
|
||||
}
|
||||
|
||||
/* Смена базового RTT при небольшой нагрузке: DATA-модель оживает, min_rtt стареет и принимает снижение без ожидания. */
|
||||
static void changing_rtt(void) {
|
||||
struct profile setting = {20,8000};
|
||||
low_load = 1; setup(&setting,1,1);
|
||||
run_for(3000,1,"rtt-low"); begin_measure();
|
||||
struct ETCP_LINK* link = ep[0].conn->links;
|
||||
CHECK(link && !link->next && link->bbr);
|
||||
expect(link->bbr->min_rtt_us < 50000,"initial RTT minimum below 50ms",link->bbr->min_rtt_us,50000);
|
||||
const unsigned rtts[] = {100,20};
|
||||
const char* phases[] = {"rtt-high","rtt-low-again"};
|
||||
for (unsigned n = 0; n < 2; n++) {
|
||||
uint64_t old_acks = link->acked_packets;
|
||||
for (int dir = 0; dir < 2; dir++) CHECK(dummynet_set_direction(channels[0],dir,rtts[n]/2,0,8000,512,0,
|
||||
"127.0.0.1",ss_get_port(&ep[1-dir].sockets[0]->local_addr)) == 0);
|
||||
profiles[0].rtt_ms = rtts[n];
|
||||
run_for(1000,1,phases[n]);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "RTT change target_ms=%u DATA_us=%u KA_us=%u jitter_us=%u RTO_us=%u min_us=%u "
|
||||
"ACKs=%llu->%llu stalled=%u retries=%u",
|
||||
rtts[n],link->data_rtt_us,link->rtt_last*100,link->data_jitter_us,etcp_tx_rto_us(link),link->bbr->min_rtt_us,
|
||||
(unsigned long long)old_acks,(unsigned long long)link->acked_packets,link->tx_stalled,ep[0].conn->retransmissions_count);
|
||||
expect(link->acked_packets > old_acks+5,"DATA ACK model progresses after RTT change",link->acked_packets,old_acks+6);
|
||||
expect(!link->tx_stalled,"live path recovered after RTT change",link->tx_stalled,0);
|
||||
if (!n) {
|
||||
expect(link->data_rtt_us > 50000,"DATA RTT learns the longer path",link->data_rtt_us,50001);
|
||||
run_for(11000,1,"rtt-high-aged");
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "RTT high aged: DATA_us=%u min_us=%u stamp_age_tb=%llu probe_us=%u ACKs=%llu",
|
||||
link->data_rtt_us,link->bbr->min_rtt_us,(unsigned long long)(get_time_tb()-link->bbr->min_rtt_stamp_tb),
|
||||
link->bbr->probe_rtt_min_us,(unsigned long long)link->acked_packets);
|
||||
expect(link->bbr->min_rtt_us >= 100000,"old short RTT minimum expires on the longer path",link->bbr->min_rtt_us,100000);
|
||||
expect(link->bbr->min_rtt_us < 130000,"new RTT minimum stays close to the 100ms path",link->bbr->min_rtt_us,130000);
|
||||
} else {
|
||||
expect(link->bbr->min_rtt_us < 50000,"lower RTT minimum learned within 1s",link->bbr->min_rtt_us,50000);
|
||||
}
|
||||
}
|
||||
measuring = 0; run_for(10000,0,"drain");
|
||||
expect(ep[0].sent == ep[1].received,"complete ordered delivery after RTT changes",ep[1].received,ep[0].sent);
|
||||
expect(!ep[0].conn->unacked_bytes,"no unacked DATA after RTT change drain",ep[0].conn->unacked_bytes,0);
|
||||
teardown();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); test_clock_init(10);
|
||||
log_bbr_samples = getenv("UTUN_BBR_SAMPLES") != NULL;
|
||||
@@ -898,6 +938,10 @@ int main(int argc, char** argv) {
|
||||
stalled(settings, faults[n].count, faults[n].broken, faults[n].directions, faults[n].mode, faults[n].sparse, faults[n].ms);
|
||||
CHECK(u_get_allocated_count() == baseline);
|
||||
}
|
||||
if (argc == 1 || !strcmp(argv[1],"rtt-change")) {
|
||||
selected++; case_name = "rtt-change"; bidirectional = 0;
|
||||
changing_rtt(); CHECK(u_get_allocated_count() == baseline);
|
||||
}
|
||||
CHECK(selected && argc <= 2);
|
||||
if (csv) CHECK(fclose(csv) == 0);
|
||||
if (diagnostic_file) {
|
||||
|
||||
Reference in new issue
Block a user