Add NAT detection with burst ping, test timing, fix port conflicts

- route_ping.c: burst mode - send next ping immediately on response
- route_ping.h: add target_ipv4/target_port/pubkey to BGP_PING_REQUEST
- test_nat_detection.c: add test for ping without embedded pubkey
- test_etcp_simple_traffic.c: use dynamic ports + fix timebase units
- Makefile.am: show test execution time in ms
This commit is contained in:
Evgeny committed 2026-04-14 14:25:36 +03:00
1 parent 31eb4a5d26
commit 7cdb84c7a2
5 files changed
+149 -81

No files matched your search

+43 -31
View File
@@ -99,8 +99,14 @@ static void route_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce,
series->rtt_sum += rtt;
}
if (series->count_sent < series->count_total && series->req->reply_conn) {
struct UTUN_INSTANCE* inst = series->req->reply_conn->instance;
series->next_timer = uasync_set_timeout(inst->ua, series->interval_ms * 10, series, route_ping_next);
if (success) {
// Ответ получен — следующий пинг сразу (burst mode)
route_ping_next(series);
} else {
// Таймаут — ждем interval_ms перед retry
struct UTUN_INSTANCE* inst = series->req->reply_conn->instance;
series->next_timer = uasync_set_timeout(inst->ua, series->interval_ms * 10, series, route_ping_next);
}
return;
}
// серия завершена
@@ -236,7 +242,7 @@ int route_ping_send_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, uint64
return -3;
}
e->dgram = (uint8_t*)req_pkt;
e->len = sizeof(struct BGP_PING_REQUEST);
e->len = offsetof(struct BGP_PING_REQUEST, target_ipv4);
int ret = etcp_send(to_conn, e);
if (ret != 0) {
@@ -275,8 +281,7 @@ int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, u
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr: invalid args");
return -1;
}
size_t extra = 6 + (pubkey ? SC_PUBKEY_SIZE : 0);
size_t pkt_size = sizeof(struct BGP_PING_REQUEST) + extra;
size_t pkt_size = pubkey ? sizeof(struct BGP_PING_REQUEST) : offsetof(struct BGP_PING_REQUEST, pubkey);
struct BGP_PING_REQUEST* req_pkt = u_calloc(1, pkt_size);
if (!req_pkt) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr: alloc failed");
@@ -289,16 +294,13 @@ int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, u
req_pkt->count = count;
req_pkt->interval_ms = interval_ms;
req_pkt->timeout_ms = timeout_ms;
uint8_t* tail = (uint8_t*)req_pkt + sizeof(struct BGP_PING_REQUEST);
tail[0] = (target_ip >> 24) & 0xFF;
tail[1] = (target_ip >> 16) & 0xFF;
tail[2] = (target_ip >> 8) & 0xFF;
tail[3] = target_ip & 0xFF;
tail[4] = (target_port >> 8) & 0xFF;
tail[5] = target_port & 0xFF;
req_pkt->target_ipv4[0] = (target_ip >> 24) & 0xFF;
req_pkt->target_ipv4[1] = (target_ip >> 16) & 0xFF;
req_pkt->target_ipv4[2] = (target_ip >> 8) & 0xFF;
req_pkt->target_ipv4[3] = target_ip & 0xFF;
req_pkt->target_port = target_port;
if (pubkey) {
memcpy(tail + 6, pubkey, SC_PUBKEY_SIZE);
memcpy(req_pkt->pubkey, pubkey, SC_PUBKEY_SIZE);
}
struct ll_entry* e = queue_entry_new(0);
@@ -352,8 +354,10 @@ void route_ping_destroy_pending(struct ROUTE_BGP* bgp) {
}
void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
if (!bgp || !from_conn || !data || len < sizeof(struct BGP_PING_REQUEST)) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_handle_req: invalid args");
const size_t base_len = offsetof(struct BGP_PING_REQUEST, target_ipv4);
const size_t addr_len = offsetof(struct BGP_PING_REQUEST, pubkey);
if (!bgp || !from_conn || !data || (len != base_len && len != addr_len && len != sizeof(struct BGP_PING_REQUEST))) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_handle_req: invalid args len=%zu", len);
return;
}
const struct BGP_PING_REQUEST* req_pkt = (const struct BGP_PING_REQUEST*)data;
@@ -367,29 +371,34 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c
struct NODEINFO_Q* target = NULL;
const uint8_t* embedded_pubkey = NULL;
if (len >= sizeof(struct BGP_PING_REQUEST) + 6) {
// Custom target address provided (for NAT ping)
const uint8_t* tail = data + sizeof(struct BGP_PING_REQUEST);
custom_socket.addr[0] = tail[0];
custom_socket.addr[1] = tail[1];
custom_socket.addr[2] = tail[2];
custom_socket.addr[3] = tail[3];
custom_socket.port = (tail[4] << 8) | tail[5];
if (len == sizeof(struct BGP_PING_REQUEST) || len == addr_len) {
// Extended packet with custom target (with or without pubkey)
custom_socket.addr[0] = req_pkt->target_ipv4[0];
custom_socket.addr[1] = req_pkt->target_ipv4[1];
custom_socket.addr[2] = req_pkt->target_ipv4[2];
custom_socket.addr[3] = req_pkt->target_ipv4[3];
custom_socket.port = req_pkt->target_port;
custom_socket.type = 0;
custom_socket.id = 0;
sockets_v4 = &custom_socket;
sock_count_v4 = 1;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_ping_handle_req: using custom target %d.%d.%d.%d:%u for node %016llx",
tail[0], tail[1], tail[2], tail[3], custom_socket.port,
(unsigned long long)req_pkt->node_id);
// Check for embedded pubkey
if (len >= sizeof(struct BGP_PING_REQUEST) + 6 + SC_PUBKEY_SIZE) {
embedded_pubkey = tail + 6;
req_pkt->target_ipv4[0], req_pkt->target_ipv4[1], req_pkt->target_ipv4[2], req_pkt->target_ipv4[3],
req_pkt->target_port, (unsigned long long)req_pkt->node_id);
// Check if embedded pubkey is non-zero (only when full packet length)
if (len == sizeof(struct BGP_PING_REQUEST)) {
int pubkey_zero = 1;
for (int i = 0; i < SC_PUBKEY_SIZE; i++) {
if (req_pkt->pubkey[i] != 0) { pubkey_zero = 0; break; }
}
if (!pubkey_zero) {
embedded_pubkey = req_pkt->pubkey;
}
}
// For custom target, we still need target node for pubkey lookup if not embedded
target = route_bgp_get_node(bgp, req_pkt->node_id);
} else {
// No custom target - look up nodeinfo for advertised sockets
} else if (len == base_len) {
// Base packet without custom target - use nodeinfo sockets
target = route_bgp_get_node(bgp, req_pkt->node_id);
if (!target) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: node %016llx not found",
@@ -407,6 +416,9 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c
}
sock_count_v4 = get_node_v4_sockets(target, &sockets_v4);
sock_count_v6 = get_node_v6_sockets(target, &sockets_v6);
} else {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: unexpected packet size %zu", len);
return;
}
if ((sock_count_v4 <= 0 || !sockets_v4) && (sock_count_v6 <= 0 || !sockets_v6)) {
+10 -7
View File
@@ -9,13 +9,16 @@
#define ROUTE_SUBCMD_PING_RESP 0x08
struct BGP_PING_REQUEST {
uint8_t cmd; // ETCP_ID_ROUTE_ENTRY
uint8_t subcmd; // ROUTE_SUBCMD_PING_REQ
uint64_t request_id; // для корреляции
uint64_t node_id; // целевой узел (должен быть известен в nodes)
uint8_t count; // число пингов
uint16_t interval_ms; // интервал между пингами
uint16_t timeout_ms; // таймаут одного пинга
uint8_t cmd; // ETCP_ID_ROUTE_ENTRY
uint8_t subcmd; // ROUTE_SUBCMD_PING_REQ
uint64_t request_id; // для корреляции
uint64_t node_id; // целевой узел
uint8_t count; // число пингов
uint16_t interval_ms; // интервал между пингами
uint16_t timeout_ms; // таймаут одного пинга
uint8_t target_ipv4[4]; // custom target IP (0 = use nodeinfo sockets)
uint16_t target_port; // custom target port
uint8_t pubkey[SC_PUBKEY_SIZE]; // pubkey for encryption if target not in nodes
} __attribute__((packed));
struct BGP_PING_RESPONSE {