From e836090a02e6f773d988b24b199abd2923b86455 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 10 Oct 2026 16:39:17 +0200 Subject: [PATCH] tests: allocate live and blackhole multilink endpoints dynamically --- tests/test_etcp_link_stress.c | 70 ++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/tests/test_etcp_link_stress.c b/tests/test_etcp_link_stress.c index 734dec5f..fa6e804a 100644 --- a/tests/test_etcp_link_stress.c +++ b/tests/test_etcp_link_stress.c @@ -5,6 +5,7 @@ #include #include "../lib/platform_compat.h" #include "test_utils.h" +#include "test_net.h" #include "etcp.h" #include "etcp_api.h" @@ -38,7 +39,8 @@ static char server_config_path[256]; static char client_config_path[256]; static int server_port = 0; static int client_port = 0; -static int next_port = 0; +static socket_t dead_sockets[3] = {SOCKET_INVALID, SOCKET_INVALID, SOCKET_INVALID}; +static unsigned dead_socket_count; static uint32_t packets_sent = 0; static uint32_t packets_received = 0; @@ -52,10 +54,6 @@ static int traffic_corrupt = 0; static int create_temp_configs(void) { if (test_mkdtemp(temp_dir) != 0) { fprintf(stderr, "Failed to create temp directory\n"); return -1; } - int base_port = 50000 + (getpid() % 15000); - server_port = base_port; - client_port = base_port + 1; - next_port = base_port + 100; snprintf(server_config_path, sizeof(server_config_path), "%s/server.conf", temp_dir); snprintf(client_config_path, sizeof(client_config_path), "%s/client.conf", temp_dir); @@ -73,12 +71,11 @@ static int create_temp_configs(void) { "keepalive_adaptive=0\n" "\n" "[server: udp0]\n" - "addr=127.0.0.1:%d\n" + "addr=127.0.0.1:0\n" "type=public\n" "\n" "[allowed_keys]\n" - "allow_all=1\n", - server_port); + "allow_all=1\n"); fclose(f); f = fopen(client_config_path, "w"); @@ -94,17 +91,16 @@ static int create_temp_configs(void) { "keepalive_adaptive=0\n" "\n" "[server: udp0]\n" - "addr=127.0.0.1:%d\n" + "addr=127.0.0.1:0\n" "type=public\n" "\n" "[client: test_client]\n" "keepalive=1\n" "peer_public_key=ce8871f07fa056c636d297115f231b08c29cdf94e0d440fce83a07c34416d36a\n" - "link=udp0:127.0.0.1:%d\n" + "link=udp0:127.0.0.1:0\n" "\n" "[allowed_keys]\n" - "allow_all=1\n", - client_port, server_port); + "allow_all=1\n"); fclose(f); return 0; } @@ -148,15 +144,28 @@ static void mk_addr(struct sockaddr_storage* out, uint16_t port) { sin->sin_port = htons(port); } -static int alloc_port(void) { return next_port++; } +// Чёрная дыра не читает INIT; удерживаем её порт, чтобы другой параллельный тест не ответил вместо неё. +static int alloc_dead_port(void) { + if (dead_socket_count == 3) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "test: too many dead endpoints"); abort(); } + socket_t sock = socket_create_udp(AF_INET); + if (sock == SOCKET_INVALID) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "test: dead socket creation failed"); abort(); } + struct sockaddr_storage address; mk_addr(&address, 0); + if (bind(sock, (struct sockaddr*)&address, sizeof(struct sockaddr_in)) != 0) { + DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "test: dead socket bind failed err=%d", socket_get_error()); abort(); + } + dead_sockets[dead_socket_count++] = sock; + return test_bound_port(sock); +} -static struct ETCP_SOCKET* add_udp_socket(struct UTUN_INSTANCE* inst, uint16_t port, const char* name) { +static struct ETCP_SOCKET* add_udp_socket(struct UTUN_INSTANCE* inst, int* port, const char* name) { struct CFG_SERVER cfg; memset(&cfg, 0, sizeof(cfg)); snprintf(cfg.name, sizeof(cfg.name), "%s", name); cfg.type = CFG_SERVER_TYPE_PUBLIC; cfg.mtu = PACKET_DATA_MAX_MTU; - mk_addr(&cfg.ip, port); - return etcp_socket_add(inst, &cfg); + mk_addr(&cfg.ip, 0); + struct ETCP_SOCKET* sock = etcp_socket_add(inst, &cfg); + if (sock) *port = ss_get_port(&sock->local_addr); + return sock; } static struct ETCP_LINK* find_link_by_remote_port(struct ETCP_CONN* conn, uint16_t port) { @@ -361,10 +370,13 @@ static int start_instances(void) { printf("failed to create server\n"); return -1; } client_instance = utun_instance_create(ua, client_config_path); + if (client_instance) test_etcp_set_peer(client_instance, "test_client", server_instance, "udp0"); if (!client_instance || utun_instance_init(client_instance) < 0) { printf("failed to create client\n"); return -1; } etcp_bind(server_instance, 0x7f, receive_test_packet); + server_port = ss_get_port(&test_etcp_bound_socket(server_instance, "udp0")->local_addr); + client_port = ss_get_port(&test_etcp_bound_socket(client_instance, "udp0")->local_addr); if (poll_until(c_conn_up_both, LINK_UP_TIMEOUT_MS, "initial connection") != 0) { printf("initial connection timeout\n"); dump_state(); return -1; } @@ -411,8 +423,8 @@ static int session_a(void) { CHECK(sc->reinit_count == srv_reinit0 && cc->reinit_count == cli_reinit0, "reinit during initial traffic"); // -- V1: клиент дозванивается до нового серверного сокета S1 -- - int sp1 = alloc_port(); - struct ETCP_SOCKET* s1 = add_udp_socket(server_instance, sp1, "dyn_s1"); + int sp1 = 0; + struct ETCP_SOCKET* s1 = add_udp_socket(server_instance, &sp1, "dyn_s1"); CHECK(s1, "V1: failed to add server socket S1"); struct sockaddr_storage s1_addr; mk_addr(&s1_addr, sp1); struct ETCP_LINK* lc1 = etcp_link_new(cc, c0, &s1_addr, 0); @@ -426,8 +438,8 @@ static int session_a(void) { CHECK(check_link_traffic(c0, sp1, "V1") == 0, "V1 link carried no traffic"); // -- V2: сервер дозванивается до клиента -- - int sp2 = alloc_port(); - struct ETCP_SOCKET* s2 = add_udp_socket(server_instance, sp2, "dyn_s2"); + int sp2 = 0; + struct ETCP_SOCKET* s2 = add_udp_socket(server_instance, &sp2, "dyn_s2"); CHECK(s2, "V2: failed to add server socket S2"); struct sockaddr_storage c0_addr; mk_addr(&c0_addr, client_port); struct ETCP_LINK* ls2 = etcp_link_new(sc, s2, &c0_addr, 0); @@ -506,13 +518,12 @@ static int session_collision(int which) { uint64_t srv_epoch = sc->reset_id, cli_epoch = cc->reset_id; CHECK(run_traffic(TRAFFIC_PACKETS, TRAFFIC_TIMEOUT_MS) == 0, "traffic before link add failed"); - int sp3 = alloc_port(); - int cp1 = alloc_port(); - int dead = alloc_port(); + int sp3 = 0, cp1 = 0; + int dead = alloc_dead_port(); - struct ETCP_SOCKET* s3 = add_udp_socket(server_instance, sp3, "dyn_s3"); + struct ETCP_SOCKET* s3 = add_udp_socket(server_instance, &sp3, "dyn_s3"); CHECK(s3, "failed to add server socket S3"); - struct ETCP_SOCKET* c1 = add_udp_socket(client_instance, cp1, "dyn_c1"); + struct ETCP_SOCKET* c1 = add_udp_socket(client_instance, &cp1, "dyn_c1"); CHECK(c1, "failed to add client socket C1"); struct sockaddr_storage s3_addr; mk_addr(&s3_addr, sp3); @@ -584,9 +595,9 @@ static int session_cross_socket(void) { CHECK(run_traffic(TRAFFIC_PACKETS, TRAFFIC_TIMEOUT_MS) == 0, "initial traffic failed"); uint32_t srv_reinit = sc->reinit_count, cli_reinit = cc->reinit_count; uint64_t srv_epoch = sc->reset_id, cli_epoch = cc->reset_id; - int sp1 = alloc_port(), cp1 = alloc_port(); - struct ETCP_SOCKET* s1 = add_udp_socket(server_instance, sp1, "cross_s1"); - struct ETCP_SOCKET* c1 = add_udp_socket(client_instance, cp1, "cross_c1"); + int sp1 = 0, cp1 = 0; + struct ETCP_SOCKET* s1 = add_udp_socket(server_instance, &sp1, "cross_s1"); + struct ETCP_SOCKET* c1 = add_udp_socket(client_instance, &cp1, "cross_c1"); CHECK(s1 && c1, "failed to add sockets"); struct sockaddr_storage c1_addr, s0_addr, s1_addr; mk_addr(&c1_addr, cp1); mk_addr(&s0_addr, server_port); mk_addr(&s1_addr, sp1); @@ -636,7 +647,7 @@ int main(void) { } printf("=== ETCP Multilink Test ===\n"); - printf("server_port=%d client_port=%d dyn_ports=%d..\n", server_port, client_port, next_port); + printf("ports assigned by the operating system for each live socket\n"); utun_instance_set_tun_init_enabled(0); ua = uasync_create(); @@ -651,6 +662,7 @@ int main(void) { if (ua) { uasync_poll(ua, 0); uasync_destroy(ua, 0); ua = NULL; } cleanup_temp_configs(); + for (unsigned i = 0; i < dead_socket_count; i++) socket_close_wrapper(dead_sockets[i]); if (rc == 0) { printf("\n=== ALL TESTS PASSED ===\n"); return 0; } printf("\n=== TESTS FAILED ===\n");