Bound ETCP receive window and fix timestamp and allocator UB

This commit is contained in:
evgeny committed 2026-09-27 12:16:15 +03:00
1 parent 59f4802904
commit 03f71fd94e
10 files changed
+211 -47

No files matched your search

+9 -2
View File
@@ -37,7 +37,7 @@
#define ETCP_RT_ID_TEST 0xF0
#define PROBE_SIZE 1024
#define SEND_BUDGET 64
#define RX_BUDGET_BYTES (16 * 1024 * 1024) /* бюджет памяти сценария при переупорядочении */
#define RX_BUDGET_BYTES (MAX_INFLIGHT_SIZE * PACKET_DATA_SIZE) /* лимит окна приёма в худшем случае */
typedef void (*timeout_cb)(void*);
enum timer_id { TIMER_DEADLINE, TIMER_PHASE, TIMER_SEND, TIMER_MONITOR, TIMER_COUNT };
@@ -57,6 +57,7 @@ static struct test_ctx {
struct UASYNC* ua;
struct NODE_CONN_DIRECT* handle;
struct ETCP_CONN* tcp_probe;
size_t allocations_before;
int round; /* 0..7 */
int step;
int ip_changes_on_last;
@@ -222,9 +223,11 @@ static void check_queues(struct pending_send* p) {
if (bytes > p->peak_bytes) p->peak_bytes = bytes;
/* Один входной пакет может дать несколько фрагментов плюс flush хвоста. */
struct PKTNORM* pn = c->normalizer;
if ((uint32_t)(c->next_tx_id - c->rx_ack_till) > MAX_INFLIGHT_SIZE + 1u)
fail("sender exceeded peer receive window");
size_t rx_bytes = queue_total_bytes(c->recv_q) + queue_total_bytes(c->output_queue) + queue_total_bytes(pn->output);
if (rx_bytes > p->peak_rx_bytes) p->peak_rx_bytes = rx_bytes;
if (rx_bytes > RX_BUDGET_BYTES) {
if (rx_bytes > RX_BUDGET_BYTES || c->recv_q->count > MAX_INFLIGHT_SIZE) {
fprintf(stderr, "receive queue overflow dir=%ld bytes=%zu budget=%u\n", (long)(p - pending), rx_bytes, RX_BUDGET_BYTES);
fail("receive queues exceeded scenario memory budget");
}
@@ -778,6 +781,7 @@ int main(void) {
debug_set_category_level(DEBUG_CATEGORY_CONNECTION, DEBUG_LEVEL_INFO);
}
utun_instance_set_tun_init_enabled(0);
ctx.allocations_before = u_get_allocated_count();
setup();
if (ctx.result) return 1;
@@ -821,6 +825,9 @@ done:
uasync_destroy(ctx.ua, 0); ctx.ua = NULL;
}
cleanup();
if (u_get_allocated_count() != ctx.allocations_before) {
u_report_unfreed_blocks(); fail("allocations leaked after fixture cleanup");
}
fprintf(stderr, "=== %s === timers/sockets cleaned\n", ctx.result == 2 ? "PASS" : "FAIL");
return (ctx.result == 2) ? 0 : 1;
}