Browse Source

tests: accelerate BGP waits and require single-link DOWN and UP

master
evgeny 2 days ago
parent
commit
3baaa42c82
  1. 6
      tests/Makefile.am
  2. 27
      tests/test_bgp_route_exchange.c
  3. 8
      tests/test_bgp_triangle.c

6
tests/Makefile.am

@ -452,13 +452,15 @@ test_route_lib_SOURCES = test_route_lib.c
test_route_lib_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib
test_route_lib_LDADD = $(LIBUTUN) $(COMMON_LIBS)
test_bgp_route_exchange_SOURCES = test_bgp_route_exchange.c test_connection_loss.h
test_bgp_route_exchange_SOURCES = test_bgp_route_exchange.c test_connection_loss.h $(test_clock_sources)
test_bgp_route_exchange_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib
test_bgp_route_exchange_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS)
test_bgp_route_exchange_LDFLAGS = $(test_clock_ldflags)
test_bgp_triangle_SOURCES = test_bgp_triangle.c test_connection_loss.h
test_bgp_triangle_SOURCES = test_bgp_triangle.c test_connection_loss.h $(test_clock_sources)
test_bgp_triangle_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib
test_bgp_triangle_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS)
test_bgp_triangle_LDFLAGS = $(test_clock_ldflags)
test_broadcast_SOURCES = test_broadcast.c
test_broadcast_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib

27
tests/test_bgp_route_exchange.c

@ -26,6 +26,7 @@
#include <sys/stat.h>
#include "../lib/platform_compat.h"
#include "test_utils.h"
#include "test_clock.h"
#ifdef _WIN32
#include <windows.h>
@ -66,6 +67,18 @@ static void* timeout_id = NULL;
// dummynet filters per link
static struct test_connection_loss loss_ab, loss_bc;
static int single_link_down, single_link_up;
static void single_link_status(struct ETCP_CONN* conn, struct ETCP_LINK* link, int old_state, int old_status, void* arg) {
(void)conn; (void)old_state;
if (link != arg || old_status == link->link_status) return;
if (link->link_status) single_link_up = 1;
else single_link_down = 1;
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "BGP single-link test: link=%u old_status=%d status=%d down=%d up=%d",
link->local_link_id, old_status, link->link_status, single_link_down, single_link_up);
}
static int cond_single_link_down(void) { return single_link_down; }
static int cond_single_link_up(void) { return single_link_up; }
static char temp_dir[] = "/tmp/utun_bgp_mesh_XXXXXX";
static char config_a[256], config_b[256], config_c[256];
@ -259,7 +272,7 @@ static void fail(const char* msg) {
static int wait_for(const char* desc, int (*cond)(void), int timeout_tb) {
uint64_t start = get_time_tb();
while (!cond() && (get_time_tb() - start) < (uint64_t)timeout_tb && test_phase == 0)
uasync_poll(ua, POLL_INTERVAL_MS);
test_clock_poll(ua, POLL_INTERVAL_MS);
if (!cond() && test_phase == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "timeout waiting for: %s", desc);
test_phase = 2;
@ -293,6 +306,7 @@ int main(void) {
debug_config_init();
debug_set_level(DEBUG_LEVEL_ERROR);
debug_set_categories(DEBUG_CATEGORY_BGP);
test_clock_init(1000);
if (getenv("UTUN_TEST_DEBUG")) {
debug_set_category_level(DEBUG_CATEGORY_BGP, DEBUG_LEVEL_DEBUG);
debug_set_category_level(DEBUG_CATEGORY_ETCP, DEBUG_LEVEL_DEBUG);
@ -348,17 +362,19 @@ int main(void) {
// --- Phase 2: Kill one A↔B link, verify routes stay ---
PHASE("2: Kill one A↔B link");
etcp_add_link_status_cbk(inst_a, single_link_status, ab_link1);
test_loss_set(&loss_ab, 1, ab_link1, NULL);
// Wait for link-down detection by keepalive, then verify routes survive (link2 still up)
for (int i = 0; i < 200 && test_phase == 0 && ab_link1->link_status; i++) uasync_poll(ua, POLL_INTERVAL_MS);
// Small margin after link-down before checks
for (int i = 0; i < 40 && test_phase == 0; i++) uasync_poll(ua, POLL_INTERVAL_MS);
// Маршрут должен пережить подтверждённый DOWN одного линка.
ASSERT(wait_for("single A-B link DOWN", cond_single_link_down, PHASE_TIMEOUT_TB), "single link did not go DOWN");
test_clock_run_for(ua, 400); // Сохраняем 40мс проверки стабильности после DOWN.
ASSERT(check_learned_route(inst_a, ntohl(inet_addr("192.168.30.0")), 24, g_node_id_c), "routes lost after 1 link down");
ASSERT(check_learned_route(inst_c, ntohl(inet_addr("192.168.10.0")), 24, g_node_id_a), "routes lost C side");
// --- Phase 3: Restore the link ---
PHASE("3: Restore one A↔B link");
test_loss_set(&loss_ab, 0, NULL, NULL);
ASSERT(wait_for("single A-B link UP", cond_single_link_up, PHASE_TIMEOUT_TB), "single link did not restore UP");
etcp_remove_link_status_cbk(inst_a, single_link_status, ab_link1);
ASSERT(wait_for("BGP recovery after ab1 restored", cond_bgp_a_to_c, PHASE_TIMEOUT_TB), "bgp A→C recovery");
// --- Phase 4: Kill B↔C link ---
@ -397,6 +413,7 @@ int main(void) {
if (ua) { uasync_poll(ua, 0); uasync_destroy(ua, 0); ua = NULL; }
cleanup_temp_configs();
test_clock_finish();
printf("=== %s ===\n", test_phase == 1 ? "TEST PASSED" : "TEST FAILED");
return test_phase == 1 ? 0 : 1;
}

8
tests/test_bgp_triangle.c

@ -29,6 +29,7 @@
#include <time.h>
#include "../lib/platform_compat.h"
#include "test_utils.h"
#include "test_clock.h"
#ifdef _WIN32
#include <windows.h>
@ -206,7 +207,7 @@ static void fail(const char* msg) {
static int wait_for(const char* desc, int (*cond)(void), int timeout_tb) {
uint64_t start = get_time_tb();
while (!cond() && (get_time_tb() - start) < (uint64_t)timeout_tb && test_phase == 0)
uasync_poll(ua, POLL_INTERVAL_MS);
test_clock_poll(ua, POLL_INTERVAL_MS);
if (!cond() && test_phase == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "timeout waiting for: %s", desc);
test_phase = 2;
@ -255,6 +256,7 @@ int main(void) {
debug_config_init();
debug_set_level(DEBUG_LEVEL_ERROR);
debug_set_categories(DEBUG_CATEGORY_BGP);
test_clock_init(1000);
const char* log = getenv("BGP_TEST_LOG");
if (log) {
debug_enable_file_output(log,1);
@ -384,8 +386,7 @@ int main(void) {
ASSERT(route_count_for_node(inst_a, g_node_id_d) > 0, "D routes missing");
ASSERT(route_count_for_node(inst_a, g_node_id_e) > 0, "E routes missing");
// Дождаться фоновых candidate probes: транзитный маршрут не является прямым peer.
uint64_t probe_deadline = get_time_tb() + 22000;
while (get_time_tb() < probe_deadline && test_phase == 0) uasync_poll(ua,POLL_INTERVAL_MS);
test_clock_run_for(ua, 22000);
struct UTUN_INSTANCE* probe_nodes[] = {inst_a,inst_b,inst_c,inst_d,inst_e};
for (size_t i = 0; i < sizeof(probe_nodes)/sizeof(probe_nodes[0]); i++)
for (struct ETCP_SOCKET* sock = probe_nodes[i]->etcp_sockets; sock; sock = sock->next)
@ -497,6 +498,7 @@ cleanup:
uasync_destroy(ua,0); ua = NULL;
}
test_clock_finish();
printf("=== %s ===\n", test_phase == 1 ? "TEST PASSED" : "TEST FAILED");
return test_phase == 1 ? 0 : 1;
}

Loading…
Cancel
Save