Measure short HOLD across resume and arm faults before propagation completes

This commit is contained in:
evgeny committed 2026-10-22 23:37:02 +02:00
1 parent 0b5a892a88
commit df5f6263bd
1 file changed
+13 -3
+13 -3
View File
@@ -326,6 +326,8 @@ static void stalled(const struct profile* settings, unsigned count, unsigned bro
if (!pkt->last_link || ((directions & 1) && traces[0][pkt->seq].first_rx)) continue;
for (unsigned p = 0; p < count; p++) if ((broken & (1u << p)) &&
ss_get_port(&pkt->last_link->remote_addr) == dummynet_get_listen_port(channels[p])) {
// Пакет должен ещё находиться в propagation delay, а не уже лежать в сокете получателя.
if ((directions & 1) && get_time_us() - traces[0][pkt->seq].first_tx >= settings[p].rtt_ms * 500ULL) continue;
pending |= 1u << p;
if (!fault_seq || pkt->seq < fault_seq) fault_seq = pkt->seq;
}
@@ -358,16 +360,23 @@ static void stalled(const struct profile* settings, unsigned count, unsigned bro
(unsigned long long)rate, (unsigned long long)capacity, fault_seq,
(unsigned long long)(traces[0][fault_seq].first_rx > fault_start ? traces[0][fault_seq].first_rx-fault_start : 0),
traces[0][fault_seq].attempts);
expect(ep[1].bytes > before, "delivery during active fault", ep[1].bytes-before, 1);
if (duration_ms > 100) expect(ep[1].bytes > before, "delivery during active fault", ep[1].bytes-before, 1);
expect(ep[1].max_gap <= MAX_GAP_US, "maximum delivery pause <=100ms", ep[1].max_gap, MAX_GAP_US);
if (sparse) expect(ep[1].max_latency <= MAX_GAP_US, "bounded-source latency <=100ms", ep[1].max_latency, MAX_GAP_US);
else if (duration_ms > 1000) expect(rate >= capacity * 85 / 100,
"fault steady goodput >=85% healthy capacity", rate, capacity * 85 / 100);
for (int i = 0; i < 2; i++) CHECK(ep[i].conn->reinit_count == epochs[i] && ep[i].conn->links_up);
measuring = 0;
measuring = duration_ms <= 100;
for (unsigned p = 0; p < count; p++) if (broken & (1u << p))
for (unsigned dir = 0; dir < 2; dir++) CHECK(dummynet_set_mode(channels[p], dir, DUMMYNET_RUN) == 0);
run_for(3000, 1, "recovery"); run_for(10000, 0, "drain");
run_for(1000, 1, "recovery");
if (duration_ms <= 100) {
expect(ep[1].samples > 0, "delivery after short HOLD", ep[1].samples, 1);
expect(ep[1].max_gap <= MAX_GAP_US, "short HOLD including resume: pause <=100ms", ep[1].max_gap, MAX_GAP_US);
expect(ep[1].max_latency <= MAX_GAP_US, "short HOLD including resume: latency <=100ms", ep[1].max_latency, MAX_GAP_US);
}
measuring = 0;
run_for(2000, 1, "recovery"); run_for(10000, 0, "drain");
for (int i = 0; i < 2; i++) expect(ep[i].sent == ep[1-i].received, "complete delivery after recovery",
ep[1-i].received, ep[i].sent);
teardown();
@@ -413,6 +422,7 @@ int main(int argc, char** argv) {
bidirectional = 0;
struct profile settings[] = {{20,8000},{20,8000},{20,2000}};
if (!strcmp(case_name, "slow-drop")) settings[1].rtt_ms = 200;
if (faults[n].count == 3) { settings[1].rtt_ms = 80; settings[2].rtt_ms = 200; }
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);
}