Cover local topology replacement allocation failures

This commit is contained in:
evgeny committed 2026-10-24 14:18:42 +02:00
1 parent f9994e11b5
commit f7db49fc97
1 file changed
+48
+48
View File
@@ -5,10 +5,13 @@
#include "utun_instance.h"
#include "routing_layer/topo_group.h"
#include "routing_layer/topo_node_sqlite.h"
#include "routing_layer/route_lib.h"
#include "config_parser.h"
#include "transport_layer/etcp.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
#include "../lib/memory_pool.h"
#include "../lib/u_async.h"
struct wire_fixture {
struct UTUN_INSTANCE inst;
@@ -296,6 +299,50 @@ static void test_bootstrap_allocation_failures(struct wire_fixture *f) {
topo_node_destroy(&f->groups, node); sqlite3_close(db);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "[PASS] SQL bootstrap: %u allocation failures and SQL failure leave no live objects/statements", total);
}
/* Уже опубликованный local_node и его маршруты переживают любой отказ подготовки новой группы. */
static void test_local_allocation_failures(struct wire_fixture *f) {
struct CFG_ROUTE_ENTRY v6 = {.ip.family = AF_INET6, .netmask = 64};
memcpy(&v6.ip.addr.v6, (uint8_t[]){0x20, 1, 0xdb, 8}, 4);
struct CFG_ROUTE_ENTRY v4 = {.next = &v6, .ip.family = AF_INET, .netmask = 24};
v4.ip.addr.v4.s_addr = htonl(0x0a010000);
struct utun_config config = {.my_subnets = &v4}; f->inst.config = &config;
f->inst.ua = uasync_create(); assert(f->inst.ua);
f->groups.node_registry = queue_new(f->inst.ua, 16, 0, 8, "local_wire_test"); assert(f->groups.node_registry);
assert(sc_generate_keypair(&f->inst.my_keys) == SC_OK);
memcpy(f->inst.my_ed25519_privkey, f->inst.my_keys.private_key, 32);
sc_derive_ed25519_pubkey(f->inst.my_keys.private_key, f->inst.my_ed25519_pubkey);
f->inst.node_id = sc_derive_node_id_from_pubkey(f->inst.my_keys.public_key);
f->inst.rt = route_table_create(f->inst.node_id); assert(f->inst.rt);
assert(!topo_node_init_self(&f->inst));
f->group.group_type = TOPO_GROUP_TYPE_UTUN;
assert(topo_group_update_my_nodeinfo(&f->inst, &f->group) == 1);
v4.ip.addr.v4.s_addr = htonl(0x0a020000);
attempts = 0; fail_at = 0; track_allocations = 1;
int rc = topo_group_update_my_nodeinfo(&f->inst, &f->group);
track_allocations = 0;
assert(rc == 1 && attempts >= 4); unsigned total = attempts;
struct TOPO_GROUP_NODE* old = f->group.local_node;
struct TOPO_NODE* node = topo_node_registry_find(&f->groups, f->inst.node_id);
uint64_t timestamp = node->timestamp; uint32_t refs = node->group_ref_count;
v4.ip.addr.v4.s_addr = htonl(0x0a030000);
for (unsigned nth = 1; nth <= total; nth++) {
size_t before = live_allocations();
attempts = 0; fail_at = nth; track_allocations = 1;
rc = topo_group_update_my_nodeinfo(&f->inst, &f->group);
track_allocations = 0;
assert(rc < 0 && attempts == nth && f->group.local_node == old && live_allocations() == before);
assert(node->timestamp == timestamp && node->group_ref_count == refs && !topo_node_verify(node));
assert(route_lookup(f->inst.rt, 0x0a020001)->v_node_info == old && !route_lookup(f->inst.rt, 0x0a030001));
}
fail_at = 0;
topo_nodeq_free_group_fields(&f->groups, old); u_free(old); f->group.local_node = NULL;
topo_node_registry_unref(&f->groups, f->inst.node_id);
assert(!f->groups.node_registry->head); queue_free(f->groups.node_registry); f->groups.node_registry = NULL;
route_table_destroy(f->inst.rt); f->inst.rt = NULL;
uasync_destroy(f->inst.ua, 0); f->inst.ua = NULL; f->inst.config = NULL;
DEBUG_INFO(DEBUG_CATEGORY_BGP, "[PASS] local group: %u allocation failures preserve identity, routes and ownership", total);
}
#endif
int main(void) {
@@ -310,6 +357,7 @@ int main(void) {
#ifdef __linux__
test_allocation_failures(&fixture);
test_bootstrap_allocation_failures(&fixture);
test_local_allocation_failures(&fixture);
#endif
fixture_destroy(&fixture);
assert(u_get_allocated_count() == before);