From 10f70a0ab27c8b80b1dcb501147d64a851e7ad06 Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Sat, 9 Aug 2025 13:57:56 +0200 Subject: irmd: Fix IPCP order in registry and query timeout Until we have a more elaborate strategy for figuring out in which Layer a service is reachable, the IRMd queries the IPCPs for names. It currently does this in the order they are stored in the registry, and the idea was to do this ordered by IPCP type. That order got messed up when the registry was rewritten. This is now fixed, with a test. The default query timeout is also lowered from 20s to 200ms. It's better to let the IRMd fail and retry the flow allocation than spend 20s waiting for the link-state routing to converge on a layer that doesn't hold the name. This does wonders for tests using Rumba... Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- src/irmd/CMakeLists.txt | 2 +- src/irmd/reg/reg.c | 15 ++++++--- src/irmd/reg/tests/reg_test.c | 71 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt index 420cda0f..965c4b3d 100644 --- a/src/irmd/CMakeLists.txt +++ b/src/irmd/CMakeLists.txt @@ -48,7 +48,7 @@ set(ENROLL_TIMEOUT 20000 CACHE STRING "Timeout for an IPCP to enroll (ms)") set(REG_TIMEOUT 20000 CACHE STRING "Timeout for registering a name (ms)") -set(QUERY_TIMEOUT 20000 CACHE STRING +set(QUERY_TIMEOUT 200 CACHE STRING "Timeout to query a name with an IPCP (ms)") set(CONNECT_TIMEOUT 20000 CACHE STRING "Timeout to connect an IPCP to another IPCP (ms)") diff --git a/src/irmd/reg/reg.c b/src/irmd/reg/reg.c index 41f8d9da..811019f6 100644 --- a/src/irmd/reg/reg.c +++ b/src/irmd/reg/reg.c @@ -151,16 +151,23 @@ static struct reg_ipcp * __reg_get_ipcp_by_layer(const char * layer) return NULL; } -static struct list_head * __reg_after_ipcp(pid_t pid) + +static struct list_head * __reg_after_ipcp(const struct ipcp_info * info) { struct list_head * p; - assert(pid > 0); + assert(info != NULL); list_for_each(p, ®.ipcps) { struct reg_ipcp * entry; entry = list_entry(p, struct reg_ipcp, next); - if (entry->info.pid > pid) + if (entry->info.type < info->type) + continue; + + if (entry->info.type > info->type) + break; + + if (entry->info.pid > info->pid) break; } @@ -780,7 +787,7 @@ int reg_create_ipcp(const struct ipcp_info * info) entry->pid = info->pid; - list_add(&ipcp->next, __reg_after_ipcp(info->pid)); + list_add_tail(&ipcp->next, __reg_after_ipcp(info)); list_add(&entry->next, __reg_after_spawned(info->pid)); reg.n_ipcps++; diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c index fab5f364..6553f316 100644 --- a/src/irmd/reg/tests/reg_test.c +++ b/src/irmd/reg/tests/reg_test.c @@ -527,7 +527,7 @@ static int test_reg_create_ipcp(void) return TEST_RC_FAIL; } -static int test_rest_reg_list_ipcps(void) +static int test_reg_list_ipcps(void) { ipcp_list_msg_t ** ipcps; int i; @@ -574,6 +574,8 @@ static int test_rest_reg_list_ipcps(void) reg_fini(); + TEST_SUCCESS(); + return TEST_RC_SUCCESS; fail: @@ -581,6 +583,70 @@ static int test_rest_reg_list_ipcps(void) return TEST_RC_FAIL; } +static int test_insert_ipcps(void) +{ + ipcp_list_msg_t ** ipcps; + struct ipcp_info info; + size_t i; + size_t len; + + TEST_START(); + + if (reg_init() < 0) { + printf("Failed to init registry.\n"); + goto fail; + } + + for (i = 0; i < 100; i++) { + sprintf(info.name, "%s-%ld", TEST_IPCP, i); + info.pid = TEST_PID + rand() % 10000; + info.type = rand() % IPCP_INVALID; + info.state = IPCP_BOOT; /* set by spawn_ipcp */ + + if (reg_create_ipcp(&info) < 0) { + printf("Failed to create ipcp %s.\n", info.name); + goto fail; + } + } + + len = reg_list_ipcps(&ipcps); + if (len != 100) { + printf("Failed to list all ipcps.\n"); + goto fail; + } + + for (i = 1; i < len; i++) { + if (ipcps[i]->type < ipcps[i - 1]->type) { + printf("IPCPS not sorted by type.\n"); + goto fail; + } + + if (ipcps[i]->type != ipcps[i - 1]->type) + continue; + + /* allow occasional duplicate PID in test */ + if (ipcps[i]->pid < ipcps[i - 1]->pid) { + printf("IPCPS not sorted by pid.\n"); + goto fail; + } + } + + while (len-- > 0) + ipcp_list_msg__free_unpacked(ipcps[len], NULL); + free(ipcps); + + reg_clear(); + + reg_fini(); + + TEST_SUCCESS(); + + return TEST_RC_SUCCESS; +fail: + REG_TEST_FAIL(); + return TEST_RC_FAIL; +} + static int test_set_layer(void) { struct reg_ipcp * ipcp; @@ -648,7 +714,8 @@ static int test_reg_ipcp(void) int rc = 0; rc |= test_reg_create_ipcp(); - rc |= test_rest_reg_list_ipcps(); + rc |= test_reg_list_ipcps(); + rc |= test_insert_ipcps(); rc |= test_set_layer(); return rc; -- cgit v1.2.3