dummynet: route between explicit independently bound endpoints

This commit is contained in:
evgeny committed 2026-10-10 16:46:19 +02:00
1 parent 70b55e4626
commit 12d4e2433e
4 files changed
+50 -92

No files matched your search

+11 -12
View File
@@ -36,12 +36,9 @@
#include "../src/config_updater.h"
#include "routing.h"
#include "crc32.h"
#include "test_net.h"
/* ===== Test constants ===== */
#define DN_PORT 21001
#define SRV_PORT 21002
#define CLI_PORT 21000
#define PAYLOAD_SIZE 1200
#define TEST_DURATION_MS 3500
#define METRICS_TB 1000 /* 100ms in 0.1ms units */
@@ -343,12 +340,14 @@ int main(void) {
ctx.sender->test_user_ptr = &ctx;
ctx.receiver->test_user_ptr = &ctx;
if (add_server(ctx.receiver, "srv", SRV_PORT) < 0 ||
add_server(ctx.sender, "local", CLI_PORT) < 0 ||
if (add_server(ctx.receiver, "srv", 0) < 0 ||
add_server(ctx.sender, "local", 0) < 0 ||
add_client(ctx.sender, s_pub) < 0) {
printf("ERROR: config setup failed\n"); return 1;
}
add_link(ctx.sender->config->clients, ctx.sender->config->servers, DN_PORT);
ctx.dn = dummynet_create(ctx.ua, "127.0.0.1", 0);
if (!ctx.dn) { printf("ERROR: dummynet_create failed\n"); return 1; }
add_link(ctx.sender->config->clients, ctx.sender->config->servers, dummynet_get_listen_port(ctx.dn));
printf("Init receiver...\n");
if (utun_instance_init(ctx.receiver) < 0) { printf("ERROR: receiver init failed\n"); return 1; }
@@ -357,16 +356,16 @@ int main(void) {
etcp_bind(ctx.receiver, ETCP_RT_ID_DATA, on_recv);
printf("Creating dummynet on port %d ...\n", DN_PORT);
ctx.dn = dummynet_create(ctx.ua, "127.0.0.1", DN_PORT);
if (!ctx.dn) { printf("ERROR: dummynet_create failed\n"); return 1; }
int receiver_port = ss_get_port(&test_etcp_bound_socket(ctx.receiver, "srv")->local_addr);
int sender_port = ss_get_port(&test_etcp_bound_socket(ctx.sender, "local")->local_addr);
printf("Ports assigned: client=%d dummynet=%u server=%d\n", sender_port, dummynet_get_listen_port(ctx.dn), receiver_port);
dummynet_set_direction(ctx.dn, DUMMYNET_FORWARD,
EMU_DELAY_MS, EMU_JITTER_MS,
EMU_BW_KBPS, EMU_QUEUE_PKTS, EMU_LOSS_PERM,
"127.0.0.1", SRV_PORT);
"127.0.0.1", (uint16_t)receiver_port);
dummynet_set_direction(ctx.dn, DUMMYNET_BACKWARD,
5, 1, 0, 200, 0,
"127.0.0.1", CLI_PORT);
"127.0.0.1", (uint16_t)sender_port);
/* Wait for connection */
printf("Waiting for connection...\n");
+14 -53
View File
@@ -12,6 +12,7 @@
#include "../lib/platform_compat.h"
#include "../lib/socket_compat.h"
#include "test_utils.h"
#include "test_net.h"
#ifdef _WIN32
#include <windows.h>
#include <direct.h>
@@ -125,40 +126,6 @@ static double toc_ms(const struct timespec* start) {
return (end.tv_sec - start->tv_sec) * 1000.0 + (end.tv_nsec - start->tv_nsec) / 1000000.0;
}
// ======================== Port allocation ========================
static int alloc_consecutive_ports(int* base_port) {
for (int attempt = 0; attempt < 200; attempt++) {
socket_t s = socket_create_udp(AF_INET);
if (s == SOCKET_INVALID) return -1;
struct sockaddr_in a;
memset(&a, 0, sizeof(a));
a.sin_family = AF_INET;
a.sin_addr.s_addr = inet_addr("127.0.0.1");
a.sin_port = 0; // auto-assign
if (bind(s, (struct sockaddr*)&a, sizeof(a)) != 0) { socket_close_wrapper(s); continue; }
socklen_t alen = sizeof(a);
getsockname(s, (struct sockaddr*)&a, &alen);
int port = ntohs(a.sin_port);
socket_close_wrapper(s);
// Need port-1, port, port+1 all free
int ok = 1;
for (int p = port - 1; p <= port + 1 && ok; p++) {
if (p < 1024) { ok = 0; break; }
socket_t ts = socket_create_udp(AF_INET);
if (ts == SOCKET_INVALID) { ok = 0; break; }
struct sockaddr_in ta;
memset(&ta, 0, sizeof(ta));
ta.sin_family = AF_INET;
ta.sin_addr.s_addr = inet_addr("127.0.0.1");
ta.sin_port = htons((uint16_t)p);
if (bind(ts, (struct sockaddr*)&ta, sizeof(ta)) != 0) ok = 0;
socket_close_wrapper(ts);
}
if (ok) { *base_port = port; return 0; }
}
return -1;
}
// ======================== Config generation ========================
static const char* srv_priv = "38240cb82199e504686507f11f6eaa4f740fde6f0c425c495e49a523019a5d68";
static const char* srv_pub = "ce8871f07fa056c636d297115f231b08c29cdf94e0d440fce83a07c34416d36a";
@@ -393,8 +360,7 @@ static int test_loopback(void) {
// ======================== Dummynet setup ========================
static int setup_dummynet(void) {
dn = dummynet_create(ua, "127.0.0.1", (uint16_t)g_dn_port);
if (!dn) { printf("[FAIL] dummynet_create on port %d\n", g_dn_port); return -1; }
if (!dn) { printf("[FAIL] dummynet listener missing\n"); return -1; }
// Forward: dummynet → server
dummynet_set_direction(dn, DUMMYNET_FORWARD, 0, 0, 0, DUMMY_QUEUE_SIZE, 0,
"127.0.0.1", (uint16_t)g_srv_port);
@@ -694,20 +660,6 @@ int main(void) {
if (!g_reset_mode) g_reset_mode = g_tcp ? "both" : "client";
if (test_mkdtemp(temp_dir) != 0) { fprintf(stderr, "mkdtemp fail\n"); return 1; }
// Allocate consecutive ports
int base_port;
if (alloc_consecutive_ports(&base_port) != 0) {
printf("[FAIL] cannot allocate consecutive ports\n");
test_rmdir(temp_dir);
return 1;
}
g_dn_port = base_port;
g_srv_port = base_port + 1;
g_cli_port = base_port - 1;
printf("Ports: dummynet=%d server=%d client=%d\n", g_dn_port, g_srv_port, g_cli_port);
write_configs();
printf("=== test_etcp_router (%s, bounded backpressure and transport recovery) ===\n", g_tcp ? "TCP" : "UDP");
debug_config_init();
@@ -725,11 +677,23 @@ int main(void) {
tic(&t_phase_start);
ua = uasync_create();
if (!ua) { printf("[FAIL] uasync_create\n"); goto done; }
if (!g_tcp) {
dn = dummynet_create(ua, "127.0.0.1", 0);
if (!dn) { printf("[FAIL] dummynet create\n"); goto done; }
g_dn_port = dummynet_get_listen_port(dn);
}
write_configs();
srv = utun_instance_create(ua, server_conf);
if (!srv || utun_instance_init(srv) < 0) { printf("[FAIL] server create\n"); goto done; }
cli = utun_instance_create(ua, client_conf);
if (cli) {
g_srv_port = ss_get_port(&test_etcp_bound_socket(srv, "s1")->local_addr);
g_cli_port = ss_get_port(&test_etcp_bound_socket(cli, "s1")->local_addr);
if (!g_tcp && setup_dummynet() != 0) { printf("[FAIL] dummynet setup\n"); goto done; }
printf("Ports: dummynet=%d server=%d client=%d\n", g_dn_port, g_srv_port, g_cli_port);
}
if (!cli || utun_instance_init(cli) < 0) { printf("[FAIL] client create\n"); goto done; }
server_node_id = srv->node_id; client_node_id = cli->node_id;
@@ -743,9 +707,6 @@ int main(void) {
}
}
// Create dummynet between client and server
if (!g_tcp && setup_dummynet() != 0) { printf("[FAIL] dummynet setup\n"); goto done; }
g_mon_id = uasync_set_timeout(ua, 100, NULL, monitor, "mon");
void* to_id = uasync_set_timeout(ua, TEST_TIMEOUT_MS * 10, NULL, timeout_cb, "to");