Repository: openthread/openthread
Pull request #11514: [posix] add runtime configuration file path support
Author: login: zesonzhang
Labels: name: platform: posix
Created: 2025-05-20T03:00:02Z | Merged: 2025-05-30T04:52:08Z

This commit enhances the POSIX platform configuration system to support
dynamic configuration file paths at runtime instead of only build-time paths.

ConfigFile class:
- Replace const char* mFilePath with char mFilePath[kFilePathMaxSize] to allow
  dynamic path updates after construction
- Add SetFilePath() and GetFilePath() methods
- Update constructor to use SetFilePath() with proper bounds checking

Configuration class:
- Add SetFactoryConfigFile() and SetProductConfigFile() methods to update
  factory and product config file paths

Radio URL parameter support:
- Add support for 'product-config-file' parameter in radio URL
- Add support for 'factory-config-file' parameter in radio URL


Diff:
diff --git a/src/posix/platform/config_file.cpp b/src/posix/platform/config_file.cpp
index bd48f56a25e..3d4c9c9f290 100644
--- a/src/posix/platform/config_file.cpp
+++ b/src/posix/platform/config_file.cpp
@@ -43,11 +43,14 @@
 namespace ot {
 namespace Posix {
 
-ConfigFile::ConfigFile(const char *aFilePath)
-    : mFilePath(aFilePath)
+ConfigFile::ConfigFile(const char *aFilePath) { SetFilePath(aFilePath); }
+
+void ConfigFile::SetFilePath(const char *aFilePath)
 {
-    assert(mFilePath != nullptr);
-    VerifyOrDie(strlen(mFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    assert(aFilePath != nullptr);
+    VerifyOrDie(strlen(aFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    strncpy(mFilePath, aFilePath, kFilePathMaxSize - 1);
+    mFilePath[kFilePathMaxSize - 1] = '\0';
 }
 
 bool ConfigFile::HasKey(const char *aKey) const
diff --git a/src/posix/platform/config_file.hpp b/src/posix/platform/config_file.hpp
index 89f4b3b8681..31ebf46d784 100644
--- a/src/posix/platform/config_file.hpp
+++ b/src/posix/platform/config_file.hpp
@@ -50,6 +50,20 @@ class ConfigFile
      */
     explicit ConfigFile(const char *aFilePath);
 
+    /**
+     * Sets the configuration file path.
+     *
+     * @param[in]  aFilePath  A pointer to the null-terminated file path.
+     */
+    void SetFilePath(const char *aFilePath);
+
+    /**
+     * Gets the configuration file path.
+     *
+     * @returns A pointer to the null-terminated file path.
+     */
+    const char *GetFilePath(void) const { return mFilePath; }
+
     /**
      * Gets a configuration from the configuration file.
      *
@@ -113,7 +127,7 @@ class ConfigFile
 
     void Strip(char *aString) const;
 
-    const char *mFilePath;
+    char mFilePath[kFilePathMaxSize];
 };
 
 } // namespace Posix
diff --git a/src/posix/platform/configuration.cpp b/src/posix/platform/configuration.cpp
index 6311bdcb165..d0a2f474df2 100644
--- a/src/posix/platform/configuration.cpp
+++ b/src/posix/platform/configuration.cpp
@@ -54,6 +54,38 @@ const char Configuration::kKeySupportedChannelMask[] = "supported_channel_mask";
 const char Configuration::kKeyPreferredChannelMask[] = "preferred_channel_mask";
 const char Configuration::kCommaDelimiter[]          = ",";
 
+otError Configuration::SetFactoryConfigFile(const char *aFilePath)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
+    mFactoryConfigFile.SetFilePath(aFilePath);
+    LogInfo("Factory configuration file path set to: %s", mFactoryConfigFile.GetFilePath());
+
+exit:
+    if (error == OT_ERROR_INVALID_ARGS)
+    {
+        LogCrit("Failed to set factory config file: %s", otThreadErrorToString(error));
+    }
+    return error;
+}
+
+otError Configuration::SetProductConfigFile(const char *aFilePath)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
+    mProductConfigFile.SetFilePath(aFilePath);
+    LogInfo("Product configuration file path set to: %s", mProductConfigFile.GetFilePath());
+
+exit:
+    if (error == OT_ERROR_INVALID_ARGS)
+    {
+        LogCrit("Failed to set product config file: %s", otThreadErrorToString(error));
+    }
+    return error;
+}
+
 otError Configuration::SetRegion(uint16_t aRegionCode)
 {
     otError       error = OT_ERROR_NONE;
diff --git a/src/posix/platform/configuration.hpp b/src/posix/platform/configuration.hpp
index aff22708f47..ce2e1d836a2 100644
--- a/src/posix/platform/configuration.hpp
+++ b/src/posix/platform/configuration.hpp
@@ -66,6 +66,28 @@ class Configuration : public Logger<Configuration>
     {
     }
 
+    /**
+     * @brief Sets the path for the factory configuration file.
+     *
+     * @param[in] aFilePath  A null-terminated C string representing the new path to the
+     *                       factory configuration file. This parameter MUST NOT be `nullptr`.
+     *
+     * @retval OT_ERROR_NONE           The factory configuration file path was successfully updated.
+     * @retval OT_ERROR_INVALID_ARGS   If @p aFilePath is `nullptr`.
+     */
+    otError SetFactoryConfigFile(const char *aFilePath);
+
+    /**
+     * @brief Sets the path for the product configuration file.
+     *
+     * @param[in] aFilePath  A null-terminated C string representing the new path to the
+     *                       product configuration file. This parameter MUST NOT be `nullptr`.
+     *
+     * @retval OT_ERROR_NONE           The product configuration file path was successfully updated.
+     * @retval OT_ERROR_INVALID_ARGS   If @p aFilePath is `nullptr`.
+     */
+    otError SetProductConfigFile(const char *aFilePath);
+
     /**
      * Set the region code.
      *
diff --git a/src/posix/platform/radio.cpp b/src/posix/platform/radio.cpp
index 3e98998ef10..071d93fc29f 100644
--- a/src/posix/platform/radio.cpp
+++ b/src/posix/platform/radio.cpp
@@ -170,6 +170,20 @@ void Radio::ProcessRadioUrl(const RadioUrl &aRadioUrl)
         mRadioSpinel.SetBusLatency(busLatency);
     }
 
+#if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
+    if (aRadioUrl.HasParam("product-config-file"))
+    {
+        const char *configFile = aRadioUrl.GetValue("product-config-file");
+        SuccessOrDie(sConfig.SetProductConfigFile(configFile));
+    }
+
+    if (aRadioUrl.HasParam("factory-config-file"))
+    {
+        const char *configFile = aRadioUrl.GetValue("factory-config-file");
+        SuccessOrDie(sConfig.SetFactoryConfigFile(configFile));
+    }
+#endif // OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
+
     ProcessMaxPowerTable(aRadioUrl);
 
 #if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
diff --git a/src/posix/platform/radio_url.cpp b/src/posix/platform/radio_url.cpp
index aef8f5b7e4e..5dd7d088dea 100644
--- a/src/posix/platform/radio_url.cpp
+++ b/src/posix/platform/radio_url.cpp
@@ -130,6 +130,14 @@ const char *otSysGetRadioUrlHelpString(void)
            "                                  Upto three IIDs can be provided with each IID separated by ',' \n"
            "                                  e.g. iid-list=1,2,3 \n"
 #endif
+#if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
+           "    product-config-file[=path]    Specify a custom path to the openthread.conf product configuration\n"
+           "                                  file.\n"
+           "                                  If not specified, the default path set at build time is used.\n"
+           "    factory-config-file[=path]    Specify a custom path to the openthread.conf factory configuration\n"
+           "                                  file.\n"
+           "                                  If not specified, the default path set at build time is used.\n"
+#endif // OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
         ;
 }
 


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR adds dynamic configuration file path management to the platform configuration system. Key changes include:
- New API methods in Configuration (SetFactoryConfigFile and SetProductConfigFile) for setting configuration file paths at runtime.
- Refactoring the ConfigFile constructor to use the new SetFilePath method.
- Enhanced error handling and logging when updating configuration paths.

### Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

| File                                        | Description                                                                        |
| ------------------------------------------- | ---------------------------------------------------------------------------------- |
| src/posix/platform/configuration.hpp        | Added API declarations for setting factory and product configuration file paths.   |
| src/posix/platform/configuration.cpp        | Implemented the new methods with error verification, logging, and error handling.  |
| src/posix/platform/config_file.hpp           | Extended ConfigFile with SetFilePath and GetFilePath methods.                      |
| src/posix/platform/config_file.cpp           | Updated the constructor to delegate file path assignment to SetFilePath.           |


<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**src/posix/platform/configuration.hpp:78**
* [nitpick] Consider renaming 'SetFactoryConfigFile' to 'SetFactoryConfigFilePath' to more clearly indicate that the method sets a file path.
```
otError SetFactoryConfigFile(const char *aFilePath);
```
**src/posix/platform/configuration.hpp:89**
* [nitpick] Consider renaming 'SetProductConfigFile' to 'SetProductConfigFilePath' for clarity that the method is updating the configuration file path.
```
otError SetProductConfigFile(const char *aFilePath);
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-05-20T03:00:18Z
user: login: zhanglongxia
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T05:44:35Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T07:40:41Z
user: login: abtink
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-22T22:47:38Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T08:35:16Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T12:45:59Z
user: login: zhanglongxia
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-28T01:56:21Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-28T05:54:59Z
user: login: zhanglongxia
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-28T08:35:46Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR adds runtime support for dynamic configuration file paths on the POSIX platform. Key changes include updating the ConfigFile class to allow dynamic file path updates, adding new methods in the Configuration class to set factory and product configuration file paths, and extending radio URL parsing to accept custom configuration file parameters.

### Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

<details>
<summary>Show a summary per file</summary>

| File                                       | Description                                                        |
| ------------------------------------------ | ------------------------------------------------------------------ |
| src/posix/platform/radio_url.cpp           | Added help string documentation for new config file URL parameters |
| src/posix/platform/radio.cpp               | Integrated new URL parameters to update configuration file paths   |
| src/posix/platform/configuration.hpp       | Declared new API methods for setting config file paths               |
| src/posix/platform/configuration.cpp       | Implemented new methods with error handling and logging              |
| src/posix/platform/config_file.hpp         | Modified ConfigFile to use a fixed-size char array and added setters   |
| src/posix/platform/config_file.cpp         | Updated constructor and SetFilePath() to support dynamic updates       |
</details>





state: COMMENTED
author_association: NONE
submitted_at: 2025-05-28T14:33:04Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-29T02:04:28Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-29T02:05:01Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR enhances the POSIX platform configuration system to support dynamic configuration file paths at runtime. It introduces new radio URL parameters to override factory and product configuration file paths, updates the ConfigFile class to use a mutable char array with bounds checking, and implements corresponding setter methods in the Configuration class.

### Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

<details>
<summary>Show a summary per file</summary>

| File                                       | Description                                                                        |
| ------------------------------------------ | ---------------------------------------------------------------------------------- |
| src/posix/platform/radio_url.cpp           | Added help text for new 'product-config-file' and 'factory-config-file' parameters.  |
| src/posix/platform/radio.cpp               | Updated radio URL processing to handle dynamic configuration file parameters.      |
| src/posix/platform/configuration.hpp       | Declared new API methods for setting configuration file paths.                     |
| src/posix/platform/configuration.cpp       | Implemented new setter functions with bounds checking and error logging.           |
| src/posix/platform/config_file.hpp         | Changed file path storage from pointer to fixed-size char array and added accessors. |
| src/posix/platform/config_file.cpp         | Revised constructor and file path setter to safely copy the file paths with checks.  |
</details>





state: COMMENTED
author_association: NONE
submitted_at: 2025-05-29T02:06:06Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-29T02:09:27Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR adds runtime support for dynamic configuration file paths on the POSIX platform, allowing users to override the default build-time paths for product and factory config files via radio URL parameters.

- Extend `ConfigFile` to store file paths in a mutable buffer and provide `SetFilePath`/`GetFilePath`.
- Add `Configuration::SetFactoryConfigFile` and `SetProductConfigFile` with logging and error handling.
- Update `radio_url.cpp` help output and `radio.cpp` processing to support new `product-config-file` and `factory-config-file` URL parameters.

### Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

<details>
<summary>Show a summary per file</summary>

| File                                      | Description                                                                                   |
|-------------------------------------------|-----------------------------------------------------------------------------------------------|
| src/posix/platform/config_file.hpp        | Replace `const char* mFilePath` with buffer, add `SetFilePath`/`GetFilePath` methods          |
| src/posix/platform/config_file.cpp        | Implement `SetFilePath` with bounds check, update constructor to use it                       |
| src/posix/platform/configuration.hpp     | Declare `SetFactoryConfigFile` and `SetProductConfigFile`                                     |
| src/posix/platform/configuration.cpp     | Implement new setters with `VerifyOrExit`, logging, and error cases                            |
| src/posix/platform/radio_url.cpp         | Add help strings for `product-config-file` and `factory-config-file` flags                     |
| src/posix/platform/radio.cpp             | Read new URL parameters and call the new configuration setters                                 |
</details>



<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**src/posix/platform/configuration.cpp:57**
* There are no existing tests exercising these new setter methods (`SetFactoryConfigFile` and `SetProductConfigFile`). Consider adding unit tests to verify behavior on valid paths, null input, and boundary cases.
```
otError Configuration::SetFactoryConfigFile(const char *aFilePath)
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-05-29T02:11:28Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR adds support for updating POSIX platform configuration file paths at runtime via the `ConfigFile` API and radio URL parameters.

- Introduce `SetFilePath`/`GetFilePath` in `ConfigFile` to allow dynamic path changes.
- Add `SetFactoryConfigFile` and `SetProductConfigFile` methods in `Configuration`.
- Enable `product-config-file` and `factory-config-file` URL parameters in the radio startup URL.

### Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

<details>
<summary>Show a summary per file</summary>

| File                                   | Description                                              |
| -------------------------------------- | -------------------------------------------------------- |
| src/posix/platform/radio_url.cpp       | Added help strings for new URL parameters                |
| src/posix/platform/radio.cpp           | Parsed and applied `product-config-file`/`factory-config-file` parameters |
| src/posix/platform/configuration.hpp   | Declared `SetFactoryConfigFile` and `SetProductConfigFile` methods |
| src/posix/platform/configuration.cpp   | Implemented the new setter methods with logging and error checks |
| src/posix/platform/config_file.hpp     | Replaced `const char*` with fixed-size buffer and getters/setters |
| src/posix/platform/config_file.cpp     | Implemented `SetFilePath` with bounds checking and `strncpy` |
</details>



<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**src/posix/platform/radio_url.cpp:134**
* Add unit tests for parsing and help-string formatting of the new `product-config-file` URL parameter to ensure correct behavior.
```
"    product-config-file[=path]    Specify a custom path to the openthread.conf product configuration\n"
```
**src/posix/platform/configuration.cpp:57**
* Add unit tests for `SetFactoryConfigFile` (and similarly for `SetProductConfigFile`) to verify error handling and log output when given valid and invalid paths.
```
otError Configuration::SetFactoryConfigFile(const char *aFilePath)
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-05-30T01:37:16Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-30T02:57:35Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-30T02:58:30Z
user: login: jwhui
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-30T03:22:44Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-30T03:32:46Z
user: login: jwhui
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-30T03:49:03Z
user: login: jwhui
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-30T04:51:47Z
user: login: zesonzhang
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-30T05:59:41Z

Review comments:
diff_hunk: @@ -66,6 +66,28 @@ class Configuration : public Logger<Configuration>
     {
     }
 
+    /**
+     * @brief Sets the path for the factory configuration file.
+     *
+     * @param[in] aFilePath  A null-terminated C string representing the new path to the
+     *                       factory configuration file. This parameter MUST NOT be `nullptr`.
+     *
+     * @retval OT_ERROR_NONE           The factory configuration file path was successfully updated.
+     * @retval OT_ERROR_INVALID_ARGS   If @p aFilePath is `nullptr`.
+     */
+    otError SetFactoryConfigFile(const char *aFilePath);
path: src/posix/platform/configuration.hpp
user: login: zhanglongxia
body: When and how to use the method `SetFactoryConfigFile` and `SetProductConfigFile`? I didn't there is a caller to call these methods.
created_at: 2025-05-20T05:32:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -44,10 +44,15 @@ namespace ot {
 namespace Posix {
 
 ConfigFile::ConfigFile(const char *aFilePath)
-    : mFilePath(aFilePath)
 {
-    assert(mFilePath != nullptr);
-    VerifyOrDie(strlen(mFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    SetFilePath(aFilePath);
+}
+
+void ConfigFile::SetFilePath(const char *aFilePath)
+{
+    assert(aFilePath != nullptr);
+    VerifyOrDie(strlen(aFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    mFilePath = aFilePath;
path: src/posix/platform/config_file.cpp
user: login: zhanglongxia
body: The original code uses the `mFilePath` to point to the file path, because the file path is a pre-defined macro. The space of the file path string will never be released. In this commit, the file path could be dynamic specified, we can't guarantee that the memory pointed by the `aFilePath` won't be released. I think we may need to store the file path like the [code](https://github.com/openthread/openthread/blob/main/src/posix/platform/settings_file.cpp#L58), rather than using a pointer to point to the file path.
created_at: 2025-05-20T05:42:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -66,6 +66,28 @@ class Configuration : public Logger<Configuration>
     {
     }
 
+    /**
+     * @brief Sets the path for the factory configuration file.
+     *
+     * @param[in] aFilePath  A null-terminated C string representing the new path to the
+     *                       factory configuration file. This parameter MUST NOT be `nullptr`.
+     *
+     * @retval OT_ERROR_NONE           The factory configuration file path was successfully updated.
+     * @retval OT_ERROR_INVALID_ARGS   If @p aFilePath is `nullptr`.
+     */
+    otError SetFactoryConfigFile(const char *aFilePath);
path: src/posix/platform/configuration.hpp
user: login: zesonzhang
body: To keep the PR small, I add these new methods here first. I will push another PR which will use these new methods.
created_at: 2025-05-20T07:40:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -66,6 +66,28 @@ class Configuration : public Logger<Configuration>
     {
     }
 
+    /**
+     * @brief Sets the path for the factory configuration file.
+     *
+     * @param[in] aFilePath  A null-terminated C string representing the new path to the
+     *                       factory configuration file. This parameter MUST NOT be `nullptr`.
+     *
+     * @retval OT_ERROR_NONE           The factory configuration file path was successfully updated.
+     * @retval OT_ERROR_INVALID_ARGS   If @p aFilePath is `nullptr`.
+     */
+    otError SetFactoryConfigFile(const char *aFilePath);
path: src/posix/platform/configuration.hpp
user: login: abtink
body: Our general policy is to add new (private/internal) method definitions and implementations along with the code that uses them within the same PR.

This way, the code is always consistent (ensuring we do not have methods defined that are not used at all). Also, as developers build the code and use the new method, it is common to want to make smaller or larger changes and improvements to the method. Including all related changes in the same PR ensures these are considered together.
created_at: 2025-05-22T22:47:38Z
author_association: MEMBER
diff_hunk: @@ -44,10 +44,15 @@ namespace ot {
 namespace Posix {
 
 ConfigFile::ConfigFile(const char *aFilePath)
-    : mFilePath(aFilePath)
 {
-    assert(mFilePath != nullptr);
-    VerifyOrDie(strlen(mFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    SetFilePath(aFilePath);
+}
+
+void ConfigFile::SetFilePath(const char *aFilePath)
+{
+    assert(aFilePath != nullptr);
+    VerifyOrDie(strlen(aFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    mFilePath = aFilePath;
path: src/posix/platform/config_file.cpp
user: login: zesonzhang
body: Thanks. I updated in the latest push.
created_at: 2025-05-23T08:35:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -66,6 +66,28 @@ class Configuration : public Logger<Configuration>
     {
     }
 
+    /**
+     * @brief Sets the path for the factory configuration file.
+     *
+     * @param[in] aFilePath  A null-terminated C string representing the new path to the
+     *                       factory configuration file. This parameter MUST NOT be `nullptr`.
+     *
+     * @retval OT_ERROR_NONE           The factory configuration file path was successfully updated.
+     * @retval OT_ERROR_INVALID_ARGS   If @p aFilePath is `nullptr`.
+     */
+    otError SetFactoryConfigFile(const char *aFilePath);
path: src/posix/platform/configuration.hpp
user: login: zesonzhang
body: Thanks @abtink , I just update with a new push.
created_at: 2025-05-27T12:45:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -130,6 +130,11 @@ const char *otSysGetRadioUrlHelpString(void)
            "                                  Upto three IIDs can be provided with each IID separated by ',' \n"
            "                                  e.g. iid-list=1,2,3 \n"
 #endif
+#if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
+           "    product-config-file[=path]    Specify a custom path to the openthread.conf product configuration "
path: src/posix/platform/radio_url.cpp
user: login: zhanglongxia
body: I saw no one calls `SetFactoryConfigFile()`. Do we also need to add a parameter `factory-config-file` to configure the factory config file? 
created_at: 2025-05-28T01:56:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -130,6 +130,11 @@ const char *otSysGetRadioUrlHelpString(void)
            "                                  Upto three IIDs can be provided with each IID separated by ',' \n"
            "                                  e.g. iid-list=1,2,3 \n"
 #endif
+#if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
+           "    product-config-file[=path]    Specify a custom path to the openthread.conf product configuration "
path: src/posix/platform/radio_url.cpp
user: login: zesonzhang
body: added a new parameter `factory-config-file`
created_at: 2025-05-28T05:54:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -54,6 +54,38 @@ const char Configuration::kKeySupportedChannelMask[] = "supported_channel_mask";
 const char Configuration::kKeyPreferredChannelMask[] = "preferred_channel_mask";
 const char Configuration::kCommaDelimiter[]          = ",";
 
+otError Configuration::SetFactoryConfigFile(const char *aFilePath)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
+    mFactoryConfigFile.SetFilePath(aFilePath);
+    LogInfo("Factory configuration file path set to: %s", mFactoryConfigFile.GetFilePath());
+
+exit:
+    if (error == OT_ERROR_INVALID_ARGS)
path: src/posix/platform/configuration.cpp
user: login: Copilot
body: [nitpick] The error handling and logging logic in SetFactoryConfigFile and SetProductConfigFile is duplicated; consider refactoring this duplication to improve maintainability.
created_at: 2025-05-28T14:33:03Z
author_association: NONE
diff_hunk: @@ -43,11 +43,13 @@
 namespace ot {
 namespace Posix {
 
-ConfigFile::ConfigFile(const char *aFilePath)
-    : mFilePath(aFilePath)
+ConfigFile::ConfigFile(const char *aFilePath) { SetFilePath(aFilePath); }
+
+void ConfigFile::SetFilePath(const char *aFilePath)
 {
-    assert(mFilePath != nullptr);
-    VerifyOrDie(strlen(mFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    assert(aFilePath != nullptr);
+    VerifyOrDie(strlen(aFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    strncpy(mFilePath, aFilePath, kFilePathMaxSize - 1);
path: src/posix/platform/config_file.cpp
user: login: Copilot
body: [nitpick] Although the VerifyOrDie check guarantees safety, explicitly setting mFilePath[kFilePathMaxSize - 1] = '\0' after strncpy can improve clarity and ensure null termination.
```suggestion
    strncpy(mFilePath, aFilePath, kFilePathMaxSize - 1);
    mFilePath[kFilePathMaxSize - 1] = '\0';
```
created_at: 2025-05-28T14:33:04Z
author_association: NONE
diff_hunk: @@ -54,6 +54,38 @@ const char Configuration::kKeySupportedChannelMask[] = "supported_channel_mask";
 const char Configuration::kKeyPreferredChannelMask[] = "preferred_channel_mask";
 const char Configuration::kCommaDelimiter[]          = ",";
 
+otError Configuration::SetFactoryConfigFile(const char *aFilePath)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
+    mFactoryConfigFile.SetFilePath(aFilePath);
+    LogInfo("Factory configuration file path set to: %s", mFactoryConfigFile.GetFilePath());
+
+exit:
+    if (error == OT_ERROR_INVALID_ARGS)
path: src/posix/platform/configuration.cpp
user: login: zesonzhang
body: To centralize the error handling may requires a new helper function added, add the error log is actually not the same. This can increase the complexity. I will keep the code as-is.
created_at: 2025-05-29T02:04:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -43,11 +43,13 @@
 namespace ot {
 namespace Posix {
 
-ConfigFile::ConfigFile(const char *aFilePath)
-    : mFilePath(aFilePath)
+ConfigFile::ConfigFile(const char *aFilePath) { SetFilePath(aFilePath); }
+
+void ConfigFile::SetFilePath(const char *aFilePath)
 {
-    assert(mFilePath != nullptr);
-    VerifyOrDie(strlen(mFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    assert(aFilePath != nullptr);
+    VerifyOrDie(strlen(aFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    strncpy(mFilePath, aFilePath, kFilePathMaxSize - 1);
path: src/posix/platform/config_file.cpp
user: login: zesonzhang
body: Updated
created_at: 2025-05-29T02:05:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -43,11 +43,14 @@
 namespace ot {
 namespace Posix {
 
-ConfigFile::ConfigFile(const char *aFilePath)
-    : mFilePath(aFilePath)
+ConfigFile::ConfigFile(const char *aFilePath) { SetFilePath(aFilePath); }
+
+void ConfigFile::SetFilePath(const char *aFilePath)
 {
-    assert(mFilePath != nullptr);
-    VerifyOrDie(strlen(mFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    assert(aFilePath != nullptr);
path: src/posix/platform/config_file.cpp
user: login: Copilot
body: [nitpick] Consider adding a comment clarifying the inclusion of kSwapSuffix in the length check to improve code clarity for future maintainers.
```suggestion
    assert(aFilePath != nullptr);
    // Ensure the combined length of the file path and the swap suffix does not exceed the maximum allowed size.
```
created_at: 2025-05-29T02:06:06Z
author_association: NONE
diff_hunk: @@ -43,11 +43,14 @@
 namespace ot {
 namespace Posix {
 
-ConfigFile::ConfigFile(const char *aFilePath)
-    : mFilePath(aFilePath)
+ConfigFile::ConfigFile(const char *aFilePath) { SetFilePath(aFilePath); }
+
+void ConfigFile::SetFilePath(const char *aFilePath)
 {
-    assert(mFilePath != nullptr);
-    VerifyOrDie(strlen(mFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    assert(aFilePath != nullptr);
path: src/posix/platform/config_file.cpp
user: login: zesonzhang
body: No need
created_at: 2025-05-29T02:09:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -43,11 +43,14 @@
 namespace ot {
 namespace Posix {
 
-ConfigFile::ConfigFile(const char *aFilePath)
-    : mFilePath(aFilePath)
+ConfigFile::ConfigFile(const char *aFilePath) { SetFilePath(aFilePath); }
+
+void ConfigFile::SetFilePath(const char *aFilePath)
 {
-    assert(mFilePath != nullptr);
-    VerifyOrDie(strlen(mFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    assert(aFilePath != nullptr);
path: src/posix/platform/config_file.cpp
user: login: Copilot
body: Using `assert` allows null-pointer checks to be omitted in release builds, potentially leading to undefined behavior. Consider replacing it with a runtime check (e.g., `VerifyOrDie`) or handling the null case explicitly.
```suggestion
    VerifyOrDie(aFilePath != nullptr, OT_EXIT_FAILURE);
```
created_at: 2025-05-29T02:11:28Z
author_association: NONE
diff_hunk: @@ -54,6 +54,38 @@ const char Configuration::kKeySupportedChannelMask[] = "supported_channel_mask";
 const char Configuration::kKeyPreferredChannelMask[] = "preferred_channel_mask";
 const char Configuration::kCommaDelimiter[]          = ",";
 
+otError Configuration::SetFactoryConfigFile(const char *aFilePath)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
+    mFactoryConfigFile.SetFilePath(aFilePath);
+    LogInfo("Factory configuration file path set to: %s", mFactoryConfigFile.GetFilePath());
+
+exit:
+    if (error == OT_ERROR_INVALID_ARGS)
+    {
+        LogCrit("Failed to set factory config file: %s", otThreadErrorToString(error));
+    }
+    return error;
+}
+
+otError Configuration::SetProductConfigFile(const char *aFilePath)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
+    mProductConfigFile.SetFilePath(aFilePath);
+    LogInfo("Product configuration file path set to: %s", mProductConfigFile.GetFilePath());
+
+exit:
+    if (error == OT_ERROR_INVALID_ARGS)
+    {
+        LogCrit("Failed to set product config file: %s", otThreadErrorToString(error));
path: src/posix/platform/configuration.cpp
user: login: Copilot
body: [nitpick] The implementations of `SetFactoryConfigFile` and `SetProductConfigFile` are nearly identical. Consider extracting the shared logic into a private helper to reduce duplication and ease future maintenance.
```suggestion
    return SetConfigFile(aFilePath, mFactoryConfigFile, "Factory configuration file");
}

otError Configuration::SetProductConfigFile(const char *aFilePath)
{
    return SetConfigFile(aFilePath, mProductConfigFile, "Product configuration file");
}

otError Configuration::SetConfigFile(const char *aFilePath, ConfigFile &aConfigFile, const char *aConfigType)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
    aConfigFile.SetFilePath(aFilePath);
    LogInfo("%s path set to: %s", aConfigType, aConfigFile.GetFilePath());

exit:
    if (error == OT_ERROR_INVALID_ARGS)
    {
        LogCrit("Failed to set %s: %s", aConfigType, otThreadErrorToString(error));
```
created_at: 2025-05-29T02:11:28Z
author_association: NONE
diff_hunk: @@ -170,6 +170,20 @@ void Radio::ProcessRadioUrl(const RadioUrl &aRadioUrl)
         mRadioSpinel.SetBusLatency(busLatency);
     }
 
+#if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
+    if (aRadioUrl.HasParam("product-config-file"))
+    {
+        const char *configFile = aRadioUrl.GetValue("product-config-file");
+        SuccessOrDie(sConfig.SetProductConfigFile(configFile));
+    }
+
+    if (aRadioUrl.HasParam("factory-config-file"))
+    {
+        const char *configFile = aRadioUrl.GetValue("factory-config-file");
+        SuccessOrDie(sConfig.SetFactoryConfigFile(configFile));
path: src/posix/platform/radio.cpp
user: login: Copilot
body: [nitpick] Using `SuccessOrDie` will abort the entire process on bad input. It may be better to propagate the error back to the caller or emit a descriptive runtime error message instead of an abrupt exit.
```suggestion
        if (sConfig.SetProductConfigFile(configFile) != OT_ERROR_NONE)
        {
            LogCrit("Failed to set product configuration file: %s", configFile);
            return; // Propagate the error or handle it appropriately.
        }
    }

    if (aRadioUrl.HasParam("factory-config-file"))
    {
        const char *configFile = aRadioUrl.GetValue("factory-config-file");
        if (sConfig.SetFactoryConfigFile(configFile) != OT_ERROR_NONE)
        {
            LogCrit("Failed to set factory configuration file: %s", configFile);
            return; // Propagate the error or handle it appropriately.
        }
```
created_at: 2025-05-29T02:11:28Z
author_association: NONE
diff_hunk: @@ -54,6 +54,38 @@ const char Configuration::kKeySupportedChannelMask[] = "supported_channel_mask";
 const char Configuration::kKeyPreferredChannelMask[] = "preferred_channel_mask";
 const char Configuration::kCommaDelimiter[]          = ",";
 
+otError Configuration::SetFactoryConfigFile(const char *aFilePath)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
+    mFactoryConfigFile.SetFilePath(aFilePath);
+    LogInfo("Factory configuration file path set to: %s", mFactoryConfigFile.GetFilePath());
+
+exit:
+    if (error == OT_ERROR_INVALID_ARGS)
+    {
+        LogCrit("Failed to set factory config file: %s", otThreadErrorToString(error));
+    }
+    return error;
+}
+
+otError Configuration::SetProductConfigFile(const char *aFilePath)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
+    mProductConfigFile.SetFilePath(aFilePath);
+    LogInfo("Product configuration file path set to: %s", mProductConfigFile.GetFilePath());
+
+exit:
+    if (error == OT_ERROR_INVALID_ARGS)
+    {
+        LogCrit("Failed to set product config file: %s", otThreadErrorToString(error));
path: src/posix/platform/configuration.cpp
user: login: Copilot
body: [nitpick] The implementations of `SetFactoryConfigFile` and `SetProductConfigFile` are nearly identical; consider refactoring common logic into a helper to reduce duplication.
```suggestion
    return SetConfigFile(aFilePath, mFactoryConfigFile, "Factory configuration file");
}

otError Configuration::SetProductConfigFile(const char *aFilePath)
{
    return SetConfigFile(aFilePath, mProductConfigFile, "Product configuration file");
}

otError Configuration::SetConfigFile(const char *aFilePath, ConfigFile &aConfigFile, const char *aLogPrefix)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
    aConfigFile.SetFilePath(aFilePath);
    LogInfo("%s path set to: %s", aLogPrefix, aConfigFile.GetFilePath());

exit:
    if (error == OT_ERROR_INVALID_ARGS)
    {
        LogCrit("Failed to set %s: %s", aLogPrefix, otThreadErrorToString(error));
```
created_at: 2025-05-30T01:37:16Z
author_association: NONE
diff_hunk: @@ -43,11 +43,14 @@
 namespace ot {
 namespace Posix {
 
-ConfigFile::ConfigFile(const char *aFilePath)
-    : mFilePath(aFilePath)
+ConfigFile::ConfigFile(const char *aFilePath) { SetFilePath(aFilePath); }
+
+void ConfigFile::SetFilePath(const char *aFilePath)
 {
-    assert(mFilePath != nullptr);
-    VerifyOrDie(strlen(mFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    assert(aFilePath != nullptr);
+    VerifyOrDie(strlen(aFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    strncpy(mFilePath, aFilePath, kFilePathMaxSize - 1);
path: src/posix/platform/config_file.cpp
user: login: Copilot
body: [nitpick] Using `strncpy` can be error-prone; consider switching to a safer function like `strlcpy` (if available) or wrapping this copy in a utility that guarantees null-termination and avoids buffer overruns.
created_at: 2025-05-30T01:37:16Z
author_association: NONE
diff_hunk: @@ -54,6 +54,38 @@ const char Configuration::kKeySupportedChannelMask[] = "supported_channel_mask";
 const char Configuration::kKeyPreferredChannelMask[] = "preferred_channel_mask";
 const char Configuration::kCommaDelimiter[]          = ",";
 
+otError Configuration::SetFactoryConfigFile(const char *aFilePath)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
+    mFactoryConfigFile.SetFilePath(aFilePath);
+    LogInfo("Factory configuration file path set to: %s", mFactoryConfigFile.GetFilePath());
+
+exit:
+    if (error == OT_ERROR_INVALID_ARGS)
+    {
+        LogCrit("Failed to set factory config file: %s", otThreadErrorToString(error));
+    }
+    return error;
+}
+
+otError Configuration::SetProductConfigFile(const char *aFilePath)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFilePath != nullptr, error = OT_ERROR_INVALID_ARGS);
+    mProductConfigFile.SetFilePath(aFilePath);
+    LogInfo("Product configuration file path set to: %s", mProductConfigFile.GetFilePath());
+
+exit:
+    if (error == OT_ERROR_INVALID_ARGS)
+    {
+        LogCrit("Failed to set product config file: %s", otThreadErrorToString(error));
path: src/posix/platform/configuration.cpp
user: login: zesonzhang
body: To centralize the error handling may requires a new helper function added, add the error log is actually not the same. This can increase the complexity. I will keep the code as-is.
created_at: 2025-05-30T02:57:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -43,11 +43,14 @@
 namespace ot {
 namespace Posix {
 
-ConfigFile::ConfigFile(const char *aFilePath)
-    : mFilePath(aFilePath)
+ConfigFile::ConfigFile(const char *aFilePath) { SetFilePath(aFilePath); }
+
+void ConfigFile::SetFilePath(const char *aFilePath)
 {
-    assert(mFilePath != nullptr);
-    VerifyOrDie(strlen(mFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    assert(aFilePath != nullptr);
+    VerifyOrDie(strlen(aFilePath) + strlen(kSwapSuffix) < kFilePathMaxSize, OT_EXIT_FAILURE);
+    strncpy(mFilePath, aFilePath, kFilePathMaxSize - 1);
path: src/posix/platform/config_file.cpp
user: login: zesonzhang
body: I will keep using strncpy which keeps the same with other implementations. 
created_at: 2025-05-30T02:58:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -130,6 +130,14 @@ const char *otSysGetRadioUrlHelpString(void)
            "                                  Upto three IIDs can be provided with each IID separated by ',' \n"
            "                                  e.g. iid-list=1,2,3 \n"
 #endif
+#if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
path: src/posix/platform/radio_url.cpp
user: login: jwhui
body: Why hide this behind a build flag? The default behavior remains the same, right?
created_at: 2025-05-30T03:22:44Z
author_association: MEMBER
diff_hunk: @@ -130,6 +130,14 @@ const char *otSysGetRadioUrlHelpString(void)
            "                                  Upto three IIDs can be provided with each IID separated by ',' \n"
            "                                  e.g. iid-list=1,2,3 \n"
 #endif
+#if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
path: src/posix/platform/radio_url.cpp
user: login: zesonzhang
body: if `OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE` is 0, these two parameters won't take effect. 

The class `ot::Posix::Configuration` is guarded by this macro, see https://github.com/openthread/openthread/blob/main/src/posix/platform/configuration.hpp#L34
created_at: 2025-05-30T03:32:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -130,6 +130,14 @@ const char *otSysGetRadioUrlHelpString(void)
            "                                  Upto three IIDs can be provided with each IID separated by ',' \n"
            "                                  e.g. iid-list=1,2,3 \n"
 #endif
+#if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
path: src/posix/platform/radio_url.cpp
user: login: jwhui
body: OK, my main concern is related to this: https://github.com/openthread/openthread/issues/5025

But I'm fine to fix this in a separate PR.
created_at: 2025-05-30T03:49:03Z
author_association: MEMBER
diff_hunk: @@ -130,6 +130,14 @@ const char *otSysGetRadioUrlHelpString(void)
            "                                  Upto three IIDs can be provided with each IID separated by ',' \n"
            "                                  e.g. iid-list=1,2,3 \n"
 #endif
+#if OPENTHREAD_POSIX_CONFIG_CONFIGURATION_FILE_ENABLE
path: src/posix/platform/radio_url.cpp
user: login: zesonzhang
body: Got it, thanks!
created_at: 2025-05-30T05:59:41Z
author_association: CONTRIBUTOR

PR comments:
user: login: size-report[bot]
created_at: 2025-05-20T03:04:48Z
body: 

# Size Report of **OpenThread**
> Merging [#11514](https://github.com/openthread/openthread/commit/26b4c5d0a6b52c35aa1bcdc6c971f957f1d0e486) into [main](https://github.com/openthread/openthread/commit/6d40977782d70d0a71e91dc82444d9486620ca5a)(6d40977782d70d0a71e91dc82444d9486620ca5a).

|  name  |  branch  |  text  | data  | bss  | total |
| :----: | :------: | -----: | ----: | ---: | ----: |
| ot-cli-ftd | main | 477632 | 860 | 66372 | 544864 |
|  | #11514 | 477632 | 860 | 66372 | 544864 |
|  | +/- | 0 | 0 | 0 | 0 |
| ot-ncp-ftd | main | 443364 | 764 | 61592 | 505720 |
|  | #11514 | 443364 | 764 | 61592 | 505720 |
|  | +/- | 0 | 0 | 0 | 0 |
| libopenthread-ftd.a | main | 244562 | 95 | 40150 | 284807 |
|  | #11514 | 244562 | 95 | 40150 | 284807 |
|  | +/- | 0 | 0 | 0 | 0 |
| libopenthread-cli-ftd.a | main | 60606 | 0 | 8083 | 68689 |
|  | #11514 | 60606 | 0 | 8083 | 68689 |
|  | +/- | 0 | 0 | 0 | 0 |
| libopenthread-ncp-ftd.a | main | 32931 | 0 | 5924 | 38855 |
|  | #11514 | 32931 | 0 | 5924 | 38855 |
|  | +/- | 0 | 0 | 0 | 0 |
| ot-cli-mtd | main | 370440 | 764 | 50860 | 422064 |
|  | #11514 | 370440 | 764 | 50860 | 422064 |
|  | +/- | 0 | 0 | 0 | 0 |
| ot-ncp-mtd | main | 351540 | 764 | 46104 | 398408 |
|  | #11514 | 351540 | 764 | 46104 | 398408 |
|  | +/- | 0 | 0 | 0 | 0 |
| libopenthread-mtd.a | main | 162932 | 0 | 24662 | 187594 |
|  | #11514 | 162932 | 0 | 24662 | 187594 |
|  | +/- | 0 | 0 | 0 | 0 |
| libopenthread-cli-mtd.a | main | 40997 | 0 | 8059 | 49056 |
|  | #11514 | 40997 | 0 | 8059 | 49056 |
|  | +/- | 0 | 0 | 0 | 0 |
| libopenthread-ncp-mtd.a | main | 25581 | 0 | 5924 | 31505 |
|  | #11514 | 25581 | 0 | 5924 | 31505 |
|  | +/- | 0 | 0 | 0 | 0 |
| ot-cli-ftd-br | main | 574632 | 868 | 133540 | 709040 |
|  | #11514 | 574632 | 868 | 133540 | 709040 |
|  | +/- | 0 | 0 | 0 | 0 |
| libopenthread-ftd-br.a | main | 345519 | 100 | 107286 | 452905 |
|  | #11514 | 345519 | 100 | 107286 | 452905 |
|  | +/- | 0 | 0 | 0 | 0 |
| libopenthread-cli-ftd-br.a | main | 75725 | 0 | 8115 | 83840 |
|  | #11514 | 75725 | 0 | 8115 | 83840 |
|  | +/- | 0 | 0 | 0 | 0 |
| ot-rcp | main | 63184 | 568 | 20804 | 84556 |
|  | #11514 | 63184 | 568 | 20804 | 84556 |
|  | +/- | 0 | 0 | 0 | 0 |
| libopenthread-rcp.a | main | 9932 | 0 | 5060 | 14992 |
|  | #11514 | 9932 | 0 | 5060 | 14992 |
|  | +/- | 0 | 0 | 0 | 0 |
| libopenthread-radio.a | main | 19269 | 0 | 238 | 19507 |
|  | #11514 | 19269 | 0 | 238 | 19507 |
|  | +/- | 0 | 0 | 0 | 0 |

author_association: NONE
user: login: codecov[bot]
created_at: 2025-05-20T04:42:41Z
body: ## [Codecov](https://app.codecov.io/gh/openthread/openthread/pull/11514?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread) Report
Attention: Patch coverage is `25.00000%` with `24 lines` in your changes missing coverage. Please review.
> Project coverage is 78.70%. Comparing base [(`6d40977`)](https://app.codecov.io/gh/openthread/openthread/commit/6d40977782d70d0a71e91dc82444d9486620ca5a?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread) to head [(`bb712f8`)](https://app.codecov.io/gh/openthread/openthread/commit/bb712f88bac107a266f910fe42a31842b179a448?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread).
> Report is 3 commits behind head on main.

| [Files with missing lines](https://app.codecov.io/gh/openthread/openthread/pull/11514?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread) | Patch % | Lines |
|---|---|---|
| [src/posix/platform/configuration.cpp](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&filepath=src%2Fposix%2Fplatform%2Fconfiguration.cpp&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread#diff-c3JjL3Bvc2l4L3BsYXRmb3JtL2NvbmZpZ3VyYXRpb24uY3Bw) | 0.00% | [18 Missing :warning: ](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread) |
| [src/posix/platform/radio.cpp](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&filepath=src%2Fposix%2Fplatform%2Fradio.cpp&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread#diff-c3JjL3Bvc2l4L3BsYXRmb3JtL3JhZGlvLmNwcA==) | 33.33% | [4 Missing :warning: ](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread) |
| [src/posix/platform/config\_file.hpp](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&filepath=src%2Fposix%2Fplatform%2Fconfig_file.hpp&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread#diff-c3JjL3Bvc2l4L3BsYXRmb3JtL2NvbmZpZ19maWxlLmhwcA==) | 0.00% | [1 Missing :warning: ](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread) |
| [src/posix/platform/radio\_url.cpp](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&filepath=src%2Fposix%2Fplatform%2Fradio_url.cpp&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread#diff-c3JjL3Bvc2l4L3BsYXRmb3JtL3JhZGlvX3VybC5jcHA=) | 0.00% | [1 Missing :warning: ](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main   #11514      +/-   ##
==========================================
+ Coverage   76.39%   78.70%   +2.31%     
==========================================
  Files         632      632              
  Lines       97130    89363    -7767     
==========================================
- Hits        74199    70331    -3868     
+ Misses      22931    19032    -3899     
```

| [Files with missing lines](https://app.codecov.io/gh/openthread/openthread/pull/11514?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread) | Coverage Δ | |
|---|---|---|
| [src/posix/platform/config\_file.cpp](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&filepath=src%2Fposix%2Fplatform%2Fconfig_file.cpp&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread#diff-c3JjL3Bvc2l4L3BsYXRmb3JtL2NvbmZpZ19maWxlLmNwcA==) | `54.02% <100.00%> (+1.08%)` | :arrow_up: |
| [src/posix/platform/configuration.hpp](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&filepath=src%2Fposix%2Fplatform%2Fconfiguration.hpp&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread#diff-c3JjL3Bvc2l4L3BsYXRmb3JtL2NvbmZpZ3VyYXRpb24uaHBw) | `100.00% <ø> (ø)` | |
| [src/posix/platform/config\_file.hpp](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&filepath=src%2Fposix%2Fplatform%2Fconfig_file.hpp&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread#diff-c3JjL3Bvc2l4L3BsYXRmb3JtL2NvbmZpZ19maWxlLmhwcA==) | `0.00% <0.00%> (ø)` | |
| [src/posix/platform/radio\_url.cpp](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&filepath=src%2Fposix%2Fplatform%2Fradio_url.cpp&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread#diff-c3JjL3Bvc2l4L3BsYXRmb3JtL3JhZGlvX3VybC5jcHA=) | `75.00% <0.00%> (ø)` | |
| [src/posix/platform/radio.cpp](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&filepath=src%2Fposix%2Fplatform%2Fradio.cpp&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread#diff-c3JjL3Bvc2l4L3BsYXRmb3JtL3JhZGlvLmNwcA==) | `91.42% <33.33%> (-0.37%)` | :arrow_down: |
| [src/posix/platform/configuration.cpp](https://app.codecov.io/gh/openthread/openthread/pull/11514?src=pr&el=tree&filepath=src%2Fposix%2Fplatform%2Fconfiguration.cpp&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread#diff-c3JjL3Bvc2l4L3BsYXRmb3JtL2NvbmZpZ3VyYXRpb24uY3Bw) | `72.41% <0.00%> (-13.31%)` | :arrow_down: |

... and [348 files with indirect coverage changes](https://app.codecov.io/gh/openthread/openthread/pull/11514/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=openthread)

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE