Fix: Network key persistence in Thread dataset
All checks were successful
Deploy Docs / build-and-deploy (push) Successful in 19s

- Network key was being reset to 0x00... after dataset updates
- Root cause: otDatasetSetActive() was overwriting the network key
- Solution: Call otThreadSetNetworkKey() before otDatasetSetActive()
  and read the key back to ensure it's included in the persistent dataset
- Verified: Network key now survives both software and hardware reboots
- Vest joins network as router in <1.1s after reboot
This commit is contained in:
2026-01-14 17:16:17 +01:00
parent fb4578ac51
commit 93a7da7855

View File

@@ -44,7 +44,7 @@ void thread_mgmt_print_dataset(const otOperationalDataset *dataset)
char net_name[OT_NETWORK_NAME_MAX_SIZE + 1] = {0};
memcpy(net_name, dataset->mNetworkName.m8, sizeof(dataset->mNetworkName.m8));
// Hex-Konvertierungen mit bin2hex
// Convert to hex strings using bin2hex
char ext_pan_id_str[17];
bin2hex(dataset->mExtendedPanId.m8, 8, ext_pan_id_str, sizeof(ext_pan_id_str));
@@ -131,7 +131,7 @@ void thread_mgmt_restart_thread_stack(device_config_payload_t *pending_config, b
// Compare each relevant field and set 'changed' if any differ
if (force || dataset.mChannel != pending_config->channel)
{
LOG_DBG("Thrad channel change detected: %u -> %u", dataset.mChannel, pending_config->channel);
LOG_DBG("Thread channel change detected: %u -> %u", dataset.mChannel, pending_config->channel);
dataset.mChannel = pending_config->channel;
dataset.mComponents.mIsChannelPresent = true;
changed = true;
@@ -154,10 +154,7 @@ void thread_mgmt_restart_thread_stack(device_config_payload_t *pending_config, b
if (force || memcmp(dataset.mNetworkKey.m8, pending_config->network_key, 16) != 0)
{
LOG_DBG("Thread network key change detected.");
LOG_HEXDUMP_DBG(dataset.mNetworkKey.m8, 16, "Old network key in dataset before update");
memcpy(dataset.mNetworkKey.m8, pending_config->network_key, 16);
LOG_HEXDUMP_DBG(pending_config->network_key, 16, "New network key from pending config");
LOG_HEXDUMP_DBG(dataset.mNetworkKey.m8, 16, "Network key in dataset after update");
dataset.mComponents.mIsNetworkKeyPresent = true;
changed = true;
}
@@ -173,14 +170,30 @@ void thread_mgmt_restart_thread_stack(device_config_payload_t *pending_config, b
if (changed)
{
LOG_DBG("Thread stack restart required; dataset changed.");
dataset.mActiveTimestamp.mSeconds++;
dataset.mComponents.mIsActiveTimestampPresent = true;
otThreadSetEnabled(instance, false);
otIp6SetEnabled(instance, false);
// Set the network key BEFORE updating the dataset
// This ensures OpenThread's crypto layer has the correct key before we update the operational dataset
otNetworkKey stored_network_key;
if (dataset.mComponents.mIsNetworkKeyPresent) {
otError key_err = otThreadSetNetworkKey(instance, &dataset.mNetworkKey);
if (key_err != OT_ERROR_NONE) {
LOG_ERR("Error setting network key: %d", key_err);
}
// Read the key back from the thread stack to ensure it's properly stored
otThreadGetNetworkKey(instance, &stored_network_key);
memcpy(dataset.mNetworkKey.m8, stored_network_key.m8, 16);
// Keep the flag set so the key is included in the persistent dataset
}
otError err = otDatasetSetActive(instance, &dataset);
if (err!= OT_ERROR_NONE) {
if (err != OT_ERROR_NONE) {
LOG_ERR("Error writing dataset: %d", err);
}
@@ -190,9 +203,10 @@ void thread_mgmt_restart_thread_stack(device_config_payload_t *pending_config, b
#if (CONFIG_THREAD_MGMT_LOG_LEVEL >= LOG_LEVEL_DBG)
otOperationalDataset new_active_dataset;
memset(&new_active_dataset, 0, sizeof(otOperationalDataset));
otDatasetGetActive(instance, &new_active_dataset);
LOG_DBG("Thread stack dataset after Thread stack update:");
thread_mgmt_print_dataset(&new_active_dataset);
if (otDatasetGetActive(instance, &new_active_dataset) == OT_ERROR_NONE) {
LOG_DBG("Thread stack dataset after Thread stack update:");
thread_mgmt_print_dataset(&new_active_dataset);
}
#endif
LOG_DBG("Thread stack restarted successfully.");
}
@@ -252,7 +266,7 @@ void thread_mgmt_get_network_name(char *dest_str, size_t max_len)
otOperationalDataset dataset;
if (otDatasetGetActive(instance, &dataset) == OT_ERROR_NONE) {
// Sicher kopieren und Null-Terminierung erzwingen
// Safe copy with forced null-termination
snprintf(dest_str, max_len, "%s", dataset.mNetworkName.m8);
}
}