diff options
author | Dimitri Staessens <dimitri@ouroboros.rocks> | 2025-08-06 12:29:02 +0200 |
---|---|---|
committer | Sander Vrijders <sander@ouroboros.rocks> | 2025-08-06 12:34:15 +0200 |
commit | fa1af6aaed6a46acd0af1600f4c63e79fcf9ff84 (patch) | |
tree | 6c386340dab2af965f9ccfc9b5b6f6e97326a586 /src/irmd | |
parent | a5f6ab5af03d9be6f3412d4dff67748908799e21 (diff) | |
download | ouroboros-fa1af6aaed6a46acd0af1600f4c63e79fcf9ff84.tar.gz ouroboros-fa1af6aaed6a46acd0af1600f4c63e79fcf9ff84.zip |
ipcpd: Update DHT for unicast layer
This is a rewrite of the DHT for name-to-address resolution in the
unicast layer. It is now integrated as a proper directory policy. The
dir_wait_running function is removed, instead the a DHT peer is passed
on during IPCP enrolment.
Each DHT request/response gets a random 64-bit ID ('cookie'). DHT
messages to the same peer are deduped, except in the case when the DHT
is low on contacts. In that case, it will contact the per it received
at enrolment for more contacts. To combat packet loss, these messages
are not deduped by means of a 'magic cookie', chosen at random when
the DHT starts.
The DHT parameters (Kademlia) can be set using the configfile or the
IRM command line tools:
if DIRECTORY_POLICY == DHT
[dht_alpha <search factor> (default: 3)]
[dht_k <replication factor> (default: 8)]
[dht_t_expire <expiration (s)> (default: 86400)]
[dht_t_refresh <contact refresh (s)> (default: 900)]
[dht_t_replicate <replication (s)> (default: 900)]
This commit also adds support for a protocol debug level (PP).
Protocol debugging for the DHT can be enabled using the
DEBUG_PROTO_DHT build flag.
The DHT has the following message types:
DHT_STORE, sent to k peers. Not acknowledged.
DHT_STORE --> [2861814146dbf9b5|ed:d9:e2:c4].
key: bcc236ab6ec69e65 [32 bytes]
val: 00000000c4e2d9ed [8 bytes]
exp: 2025-08-03 17:29:44 (UTC).
DHT_FIND_NODE_REQ, sent to 'alpha' peers, with a corresponding
response. This is used to update the peer routing table to iteratively
look for the nodes with IDs closest to the requested key.
DHT_FIND_NODE_REQ --> [a62f92abffb451c4|ed:d9:e2:c4].
cookie: 2d4b7acef8308210
key: a62f92abffb451c4 [32 bytes]
DHT_FIND_NODE_RSP <-- [2861814146dbf9b5|ed:d9:e2:c4].
cookie: 2d4b7acef8308210
key: a62f92abffb451c4 [32 bytes]
contacts: [1]
[a62f92abffb451c4|9f:0d:c1:fb]
DHT_FIND_VALUE_REQ, sent to 'k' peers, with a corresponding
response. Used to find a value for a key. Will also send its closest
known peers in the response.
DHT_FIND_VALUE_REQ --> [2861814146dbf9b5|ed:d9:e2:c4].
cookie: 80a1adcb09a2ff0a
key: 42dee3b0415b4f69 [32 bytes]
DHT_FIND_VALUE_RSP <-- [2861814146dbf9b5|ed:d9:e2:c4].
cookie: 80a1adcb09a2ff0a
key: 42dee3b0415b4f69 [32 bytes]
values: [1]
00000000c4e2d9ed [8 bytes]
contacts: [1]
[a62f92abffb451c4|9f:0d:c1:fb]
Also removes ubuntu 20 from appveyor config as it is not supported anymore.
Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/irmd')
-rw-r--r-- | src/irmd/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/irmd/config.h.in | 2 | ||||
-rw-r--r-- | src/irmd/configfile.c | 114 | ||||
-rw-r--r-- | src/irmd/main.c | 6 | ||||
-rw-r--r-- | src/irmd/reg/reg.c | 5 |
5 files changed, 111 insertions, 18 deletions
diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt index 312578de..420cda0f 100644 --- a/src/irmd/CMakeLists.txt +++ b/src/irmd/CMakeLists.txt @@ -23,8 +23,8 @@ if (LIBTOML_LIBRARIES) install(FILES "${CMAKE_BINARY_DIR}/irmd.conf.example" DESTINATION "${OUROBOROS_CONFIG_DIR}") unset(INSTALL_DIR) - mark_as_advanced(LIBTOML_LIBRARIES) find_path(LIBTOML_INCLUDE toml.h) + mark_as_advanced(LIBTOML_LIBRARIES LIBTOML_INCLUDE) else () message(STATUS "Configuration file support disabled by user") unset(OUROBOROS_CONFIG_FILE CACHE) diff --git a/src/irmd/config.h.in b/src/irmd/config.h.in index 11b9d11f..8bf02e06 100644 --- a/src/irmd/config.h.in +++ b/src/irmd/config.h.in @@ -67,7 +67,9 @@ #cmakedefine IRMD_KILL_ALL_PROCESSES #cmakedefine HAVE_LIBGCRYPT #cmakedefine HAVE_OPENSSL +#ifdef CONFIG_OUROBOROS_DEBUG #cmakedefine DEBUG_PROTO_OAP +#endif #define O7S_ASCII_ART \ "[0m\n" \ diff --git a/src/irmd/configfile.c b/src/irmd/configfile.c index 279af80f..f8948c2c 100644 --- a/src/irmd/configfile.c +++ b/src/irmd/configfile.c @@ -52,6 +52,7 @@ #endif #define ERRBUFSZ 200 +#define DATUMSZ 256 static int toml_hash(toml_table_t * table, struct layer_info * info) @@ -217,6 +218,99 @@ static int toml_broadcast(toml_table_t * table, return 0; } +#define BETWEEN(a, b, c) ((a) >= (b) && (a) <= (c)) +#define DHT(conf, x) (conf)->dht.params.x +static int toml_dir(toml_table_t * table, + struct dir_config * conf) +{ + toml_datum_t dir; + toml_datum_t alpha; + toml_datum_t t_expire; + toml_datum_t t_refresh; + toml_datum_t t_replicate; + toml_datum_t k; + + dir = toml_string_in(table, "directory"); + if (dir.ok) { + log_dbg("Found directory type: %s", dir.u.s); + if (strlen(dir.u.s) > DATUMSZ) { + log_err("Directory name too long: %s", dir.u.s); + free(dir.u.s); + return -1; + } + if (strcmp(dir.u.s, "DHT") == 0) + conf->pol = DIR_DHT; + else if (strcmp(dir.u.s, "dht") == 0) + conf->pol = DIR_DHT; + else { + log_err("Unknown directory type: %s", dir.u.s); + free(dir.u.s); + return -EINVAL; + } + free(dir.u.s); + } + + switch(conf->pol) { + case DIR_DHT: + log_info("Using DHT directory policy."); + alpha = toml_int_in(table, "dht_alpha"); + if (alpha.ok) { + if (!BETWEEN(alpha.u.i, + DHT_ALPHA_MIN, DHT_ALPHA_MAX)) { + log_err("Invalid alpha value: %ld", + alpha.u.i); + return -EINVAL; + } + DHT(conf, alpha) = alpha.u.i; + } + t_expire = toml_int_in(table, "dht_t_expire"); + if (t_expire.ok) { + if (!BETWEEN(t_expire.u.i, + DHT_T_EXPIRE_MIN, DHT_T_EXPIRE_MAX)) { + log_err("Invalid expire time: %ld", + t_expire.u.i); + return -EINVAL; + } + DHT(conf, t_expire) = t_expire.u.i; + } + t_refresh = toml_int_in(table, "dht_t_refresh"); + if (t_refresh.ok) { + if (!BETWEEN(t_refresh.u.i, + DHT_T_REFRESH_MIN, DHT_T_REFRESH_MAX)) { + log_err("Invalid refresh time: %ld", + t_refresh.u.i); + return -EINVAL; + } + DHT(conf, t_refresh) = t_refresh.u.i; + } + t_replicate = toml_int_in(table, "dht_t_replicate"); + if (t_replicate.ok) { + if (!BETWEEN(t_replicate.u.i, + DHT_T_REPLICATE_MIN, DHT_T_REPLICATE_MAX)) { + log_err("Invalid replication time: %ld", + t_replicate.u.i); + return -EINVAL; + } + DHT(conf, t_replicate) = t_replicate.u.i; + } + k = toml_int_in(table, "dht_k"); + if (k.ok) { + if (!BETWEEN(k.u.i, DHT_K_MIN, DHT_K_MAX)) { + log_err("Invalid replication factor: %ld", + k.u.i); + return -EINVAL; + } + DHT(conf, k) = k.u.i; + } + break; + default: + assert(false); + break; + } + + return 0; +} + static int toml_routing(toml_table_t * table, struct dt_config * conf) { @@ -314,12 +408,12 @@ static int toml_dt(toml_table_t * table, static int toml_unicast(toml_table_t * table, struct ipcp_config * conf) { - - *conf = uni_default_conf; - if (toml_hash(table, &conf->layer_info) < 0) + if (toml_dir(table, &conf->unicast.dir) < 0) { + log_err("Invalid directory configuration."); return -1; + } if (toml_dt(table, &conf->unicast.dt) < 0) { log_err("Invalid DT configuration."); @@ -336,6 +430,7 @@ static int toml_unicast(toml_table_t * table, return -1; } + return 0; } @@ -566,7 +661,7 @@ static int toml_ipcp_list(toml_table_t * table, } info.type = type; - strcpy(info.name,key); + strcpy(info.name, key); conf.type = type; ret = toml_ipcp(toml_table_in(table, key), &info, &conf); @@ -765,8 +860,9 @@ static int toml_toplevel(toml_table_t * table, toml_table_t * subtable; subtable = toml_table_in(table, key); - - if (strcmp(key, "local") == 0) + if (strcmp(key, "name") == 0) + return toml_name_list(subtable); + else if (strcmp(key, "local") == 0) return toml_ipcp_list(subtable, IPCP_LOCAL); else if (strcmp(key, "eth-dix") == 0) return toml_ipcp_list(subtable, IPCP_ETH_DIX); @@ -778,10 +874,8 @@ static int toml_toplevel(toml_table_t * table, return toml_ipcp_list(subtable, IPCP_BROADCAST); else if (strcmp(key, "unicast") == 0) return toml_ipcp_list(subtable, IPCP_UNICAST); - else if (strcmp(key, "name") == 0) - return toml_name_list(subtable); - - log_err("Unkown toplevel key: %s.", key); + else + log_err("Unkown toplevel key: %s.", key); return -1; } diff --git a/src/irmd/main.c b/src/irmd/main.c index bf94354f..5be38174 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -1393,7 +1393,7 @@ static void * acceptloop(void * o) return (void *) 0; } -static void free_msg(void * o) +static void __cleanup_irm_msg(void * o) { irm_msg__free_unpacked((irm_msg_t *) o, NULL); } @@ -1437,7 +1437,7 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg) ret_msg->code = IRM_MSG_CODE__IRM_REPLY; - pthread_cleanup_push(free_msg, ret_msg); + pthread_cleanup_push(__cleanup_irm_msg, ret_msg); switch (msg->code) { case IRM_MSG_CODE__IRM_CREATE_IPCP: @@ -1636,7 +1636,7 @@ static void * mainloop(void * o) tpm_begin_work(irmd.tpm); pthread_cleanup_push(__cleanup_close_ptr, &sfd); - pthread_cleanup_push(free_msg, msg); + pthread_cleanup_push(__cleanup_irm_msg, msg); ret_msg = do_command_msg(msg); diff --git a/src/irmd/reg/reg.c b/src/irmd/reg/reg.c index 1ecc5451..41f8d9da 100644 --- a/src/irmd/reg/reg.c +++ b/src/irmd/reg/reg.c @@ -885,12 +885,9 @@ int reg_list_ipcps(ipcp_list_msg_t *** ipcps) list_for_each(p, ®.ipcps) { struct reg_ipcp * entry; - log_dbg("Creating ipcp list info %d.", i); entry = list_entry(p, struct reg_ipcp, next); - if (__get_ipcp_info(&(*ipcps)[i], entry) < 0) { - log_err("Failed to create ipcp list info."); + if (__get_ipcp_info(&(*ipcps)[i], entry) < 0) goto fail; - } i++; } |