mirror of
https://github.com/espressif/openthread.git
synced 2026-06-05 21:14:49 +00:00
[multi-ail-detector] allow detector to run independently of Border Routing (#12078)
This commit updates the Multi-AIL Detection feature to operate independently of the Border Routing Manager. This fundamental change allows the detector to be enabled/disabled on its own, rather than being tied to the Border Routing Manager's state. This change also moves the Multi-AIL detection API into a separate `openthread/multi_ail_detection.h` header and introduces new APIs to control the detector independently. Corresponding CLI commands are also added. The `test-505-multi-ail-detection.py` is also updated to validate this new independent behavior. In particular that a device that is not enabled to act as a BR can independently run multi-AIL detection and determine whether, if it becomes a BR, it will cause multi-AIL issues.
This commit is contained in:
committed by
GitHub
parent
61e43cffb9
commit
eb51d4be51
@@ -119,6 +119,7 @@
|
||||
* @defgroup api-border-agent-txt-data Border Agent TXT Data Parser
|
||||
* @defgroup api-border-router Border Router
|
||||
* @defgroup api-border-routing Border Routing Manager
|
||||
* @defgroup api-multi-ail-detection Border Router Multi AIL Detection
|
||||
* @defgroup api-commissioner Commissioner
|
||||
* @defgroup api-thread-general General
|
||||
* @brief This module includes functions for all Thread roles.
|
||||
|
||||
@@ -78,6 +78,7 @@ source_set("openthread") {
|
||||
"mdns.h",
|
||||
"mesh_diag.h",
|
||||
"message.h",
|
||||
"multi_ail_detection.h",
|
||||
"multi_radio.h",
|
||||
"nat64.h",
|
||||
"ncp.h",
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <openthread/error.h>
|
||||
#include <openthread/instance.h>
|
||||
#include <openthread/ip6.h>
|
||||
#include <openthread/multi_ail_detection.h> // IWYU pragma: keep
|
||||
#include <openthread/netdata.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -641,68 +642,6 @@ otError otBorderRoutingGetNextPeerBrEntry(otInstance *
|
||||
*/
|
||||
uint16_t otBorderRoutingCountPeerBrs(otInstance *aInstance, uint32_t *aMinAge);
|
||||
|
||||
/**
|
||||
* A callback function pointer called when the multi-AIL detection state changes.
|
||||
*
|
||||
* This callback function is invoked by the OpenThread stack whenever the Routing Manager determines a change in
|
||||
* whether Border Routers on the Thread mesh might be connected to different Adjacent Infrastructure Links (AILs).
|
||||
*
|
||||
* See `otBorderRoutingIsMultiAilDetected()` for more details.
|
||||
*
|
||||
* @param[in] aDetected `TRUE` if multiple AILs are now detected, `FALSE` otherwise.
|
||||
* @param[in] aContext A pointer to arbitrary context information provided when the callback was registered
|
||||
* using `otBorderRoutingSetMultiAilCallback()`.
|
||||
*/
|
||||
typedef void (*otBorderRoutingMultiAilCallback)(bool aDetected, void *aContext);
|
||||
|
||||
/**
|
||||
* Gets the current detected state regarding multiple Adjacent Infrastructure Links (AILs).
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE`.
|
||||
*
|
||||
* It returns whether the Routing Manager currently believes that Border Routers (BRs) on the Thread mesh may be
|
||||
* connected to different AILs.
|
||||
*
|
||||
* The detection mechanism operates as follows: The Routing Manager monitors the number of peer BRs listed in the
|
||||
* Thread Network Data (see `otBorderRoutingCountPeerBrs()`) and compares this count with the number of peer BRs
|
||||
* discovered by processing received Router Advertisement (RA) messages on its connected AIL. If the count derived from
|
||||
* Network Data consistently exceeds the count derived from RAs for a detection duration of 10 minutes, it concludes
|
||||
* that BRs are likely connected to different AILs. To clear state a shorter window of 1 minute is used.
|
||||
*
|
||||
* The detection window of 10 minutes helps to avoid false positives due to transient changes. The Routing Manager uses
|
||||
* 200 seconds for reachability checks of peer BRs (sending Neighbor Solicitation). Stale Network Data entries are
|
||||
* also expected to age out within a few minutes. So a 10-minute detection time accommodates both cases.
|
||||
*
|
||||
* While generally effective, this detection mechanism may get less reliable in scenarios with a large number of
|
||||
* BRs, particularly exceeding ten. This is related to the "Network Data Publisher" mechanism, where BRs might refrain
|
||||
* from publishing their external route information in the Network Data to conserve its limited size, potentially
|
||||
* skewing the Network Data BR count.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
*
|
||||
* @retval TRUE Has detected that BRs are likely connected to multiple AILs.
|
||||
* @retval FALSE Has not detected (or no longer detects) that BRs are connected to multiple AILs.
|
||||
*/
|
||||
bool otBorderRoutingIsMultiAilDetected(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Sets a callback function to be notified of changes in the multi-AIL detection state.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE`.
|
||||
*
|
||||
* Subsequent calls to this function will overwrite the previous callback setting. Using `NULL` for @p aCallback will
|
||||
* disable the callback.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
* @param[in] aCallback A pointer to the function (`otBorderRoutingMultiAilCallback`) to be called
|
||||
* upon state changes, or `NULL` to unregister a previously set callback.
|
||||
* @param[in] aContext A pointer to application-specific context that will be passed back
|
||||
* in the `aCallback` function. This can be `NULL` if no context is needed.
|
||||
*/
|
||||
void otBorderRoutingSetMultiAilCallback(otInstance *aInstance,
|
||||
otBorderRoutingMultiAilCallback aCallback,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* Iterates over the Recursive DNS Server (RDNSS) address entries.
|
||||
*
|
||||
|
||||
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (549)
|
||||
#define OPENTHREAD_API_VERSION (550)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2025, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file defines the OpenThread Border Router Multi-AIL Detection API.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_MULTI_AIL_DETECTION_H_
|
||||
#define OPENTHREAD_MULTI_AIL_DETECTION_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <openthread/instance.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup api-multi-ail-detection
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions for the OpenThread Multi-AIL Detection feature.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* All the functions in this module require both the `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` and
|
||||
* `OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE` to be enabled.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A callback function pointer called when the multi-AIL detection state changes.
|
||||
*
|
||||
* This callback function is invoked by the OpenThread stack whenever the detector determines a change in whether
|
||||
* Border Routers on the Thread mesh might be connected to different Adjacent Infrastructure Links (AILs).
|
||||
*
|
||||
* See `otBorderRoutingIsMultiAilDetected()` for more details.
|
||||
*
|
||||
* @param[in] aDetected `TRUE` if multiple AILs are now detected, `FALSE` otherwise.
|
||||
* @param[in] aContext A pointer to arbitrary context information provided when the callback was registered
|
||||
* using `otBorderRoutingSetMultiAilCallback()`.
|
||||
*/
|
||||
typedef void (*otBorderRoutingMultiAilCallback)(bool aDetected, void *aContext);
|
||||
|
||||
/**
|
||||
* Enables or disables the Multi-AIL Detector.
|
||||
*
|
||||
* If `OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_AUTO_ENABLE_MODE` is enabled, the detector is enabled
|
||||
* by default and starts running when the infra-if network is initialized and becomes active (running).
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
* @param[in] aEnable TRUE to enable the detector, FALSE to disable.
|
||||
*/
|
||||
void otBorderRoutingSetMultiAilDetectionEnabled(otInstance *aInstance, bool aEnable);
|
||||
|
||||
/**
|
||||
* Checks if the Multi-AIL Detector is enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
*
|
||||
* @retval TRUE If the detector is enabled.
|
||||
* @retval FALSE If the detector is disabled.
|
||||
*/
|
||||
bool otBorderRoutingIsMultiAilDetectionEnabled(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Checks if the Multi-AIL Detector is running.
|
||||
*
|
||||
* The detector runs when it is enabled and the infrastructure interface is also active.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
*
|
||||
* @retval TRUE If the detector is running.
|
||||
* @retval FALSE If the detector is not running.
|
||||
*/
|
||||
bool otBorderRoutingIsMultiAilDetectionRunning(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Gets the current detected state regarding multiple Adjacent Infrastructure Links (AILs).
|
||||
*
|
||||
* It returns whether the detector currently believes that Border Routers (BRs) on the Thread mesh may be connected to
|
||||
* different AILs.
|
||||
*
|
||||
* The detection mechanism operates as follows: The detector monitors the number of peer BRs listed in the
|
||||
* Thread Network Data (see `otBorderRoutingCountPeerBrs()`) and compares this count with the number of peer BRs
|
||||
* discovered by processing received Router Advertisement (RA) messages on its connected AIL. If the count derived from
|
||||
* Network Data consistently exceeds the count derived from RAs for a detection duration of 10 minutes, it concludes
|
||||
* that BRs are likely connected to different AILs. To clear state a shorter window of 1 minute is used.
|
||||
*
|
||||
* The detection window of 10 minutes helps to avoid false positives due to transient changes. The detector uses
|
||||
* 200 seconds for reachability checks of peer BRs (sending Neighbor Solicitation). Stale Network Data entries are
|
||||
* also expected to age out within a few minutes. So a 10-minute detection time accommodates both cases.
|
||||
*
|
||||
* While generally effective, this detection mechanism may get less reliable in scenarios with a large number of
|
||||
* BRs, particularly exceeding ten. This is related to the "Network Data Publisher" mechanism, where BRs might refrain
|
||||
* from publishing their external route information in the Network Data to conserve its limited size, potentially
|
||||
* skewing the Network Data BR count.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
*
|
||||
* @retval TRUE Has detected that BRs are likely connected to multiple AILs.
|
||||
* @retval FALSE Has not detected (or no longer detects) that BRs are connected to multiple AILs.
|
||||
*/
|
||||
bool otBorderRoutingIsMultiAilDetected(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Sets a callback function to be notified of changes in the multi-AIL detection state.
|
||||
*
|
||||
* Subsequent calls to this function will overwrite the previous callback setting. Using `NULL` for @p aCallback will
|
||||
* disable the callback.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
* @param[in] aCallback A pointer to the function (`otBorderRoutingMultiAilCallback`) to be called
|
||||
* upon state changes, or `NULL` to unregister a previously set callback.
|
||||
* @param[in] aContext A pointer to application-specific context that will be passed back
|
||||
* in the `aCallback` function. This can be `NULL` if no context is needed.
|
||||
*/
|
||||
void otBorderRoutingSetMultiAilCallback(otInstance *aInstance,
|
||||
otBorderRoutingMultiAilCallback aCallback,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_MULTI_AIL_DETECTION_H_
|
||||
@@ -198,6 +198,34 @@ Done
|
||||
BR multi AIL callback: cleared
|
||||
```
|
||||
|
||||
Usage: `br multiail state`
|
||||
|
||||
Outputs full state of multi-AIL detector:
|
||||
|
||||
- Whether the detector is enabled.
|
||||
- Whether the detector is running (when it is enabled and the infra-if interface is also active).
|
||||
- Whether multi-AIL was detected.
|
||||
|
||||
```bash
|
||||
> br multiail state
|
||||
Enabled: yes
|
||||
Running: yes
|
||||
Detected: no
|
||||
Done
|
||||
```
|
||||
|
||||
Usage: `br multiail enable|disable`
|
||||
|
||||
Enable or disable the multi-AIL detector.
|
||||
|
||||
```bash
|
||||
> br multiail enable
|
||||
Done
|
||||
|
||||
> br multiail disable
|
||||
Done
|
||||
```
|
||||
|
||||
### omrconfig
|
||||
|
||||
Usage: `br omrconfig`
|
||||
|
||||
@@ -197,6 +197,40 @@ template <> otError Br::Process<Cmd("multiail")>(Arg aArgs[])
|
||||
|
||||
otBorderRoutingSetMultiAilCallback(GetInstancePtr(), callback, this);
|
||||
}
|
||||
/**
|
||||
* @cli br multiail state
|
||||
* @code
|
||||
* br multiail state
|
||||
* Enabled: yes
|
||||
* Running: yes
|
||||
* Detected: no
|
||||
* Done
|
||||
* @endcode
|
||||
* @par
|
||||
* Outputs full state of multi-AIL detector:
|
||||
* - Whether the detector is enabled.
|
||||
* - Whether the detector is running (when it is enabled and the infra-if interface is also active).
|
||||
* - Whether multi-AIL was detected.
|
||||
*/
|
||||
else if (aArgs[0] == "state")
|
||||
{
|
||||
OutputLine("Enabled: %s", otBorderRoutingIsMultiAilDetectionEnabled(GetInstancePtr()) ? "yes" : "no");
|
||||
OutputLine("Running: %s", otBorderRoutingIsMultiAilDetectionRunning(GetInstancePtr()) ? "yes" : "no");
|
||||
OutputLine("Detected: %s", otBorderRoutingIsMultiAilDetected(GetInstancePtr()) ? "yes" : "no");
|
||||
}
|
||||
/**
|
||||
* @cli br multiail (enable, disable)
|
||||
* @code
|
||||
* br multiail enable
|
||||
* Done
|
||||
* @endcode
|
||||
* @cparam br multiail @ca{enable|disable}
|
||||
* @par api_copy
|
||||
* #otBorderRoutingSetMultiAilDetectionEnabled
|
||||
*/
|
||||
else if (ProcessEnableDisable(aArgs, otBorderRoutingSetMultiAilDetectionEnabled) == OT_ERROR_NONE)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_INVALID_ARGS;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/border_routing.h>
|
||||
#include <openthread/multi_ail_detection.h>
|
||||
|
||||
#include "cli/cli_config.h"
|
||||
#include "cli/cli_history.hpp"
|
||||
|
||||
@@ -343,6 +343,7 @@ openthread_core_files = [
|
||||
"api/mdns_api.cpp",
|
||||
"api/mesh_diag_api.cpp",
|
||||
"api/message_api.cpp",
|
||||
"api/multi_ail_detection_api.cpp",
|
||||
"api/multi_radio_api.cpp",
|
||||
"api/nat64_api.cpp",
|
||||
"api/netdata_api.cpp",
|
||||
|
||||
@@ -67,6 +67,7 @@ set(COMMON_SOURCES
|
||||
api/mdns_api.cpp
|
||||
api/mesh_diag_api.cpp
|
||||
api/message_api.cpp
|
||||
api/multi_ail_detection_api.cpp
|
||||
api/multi_radio_api.cpp
|
||||
api/nat64_api.cpp
|
||||
api/netdata_api.cpp
|
||||
|
||||
@@ -293,22 +293,6 @@ uint16_t otBorderRoutingCountPeerBrs(otInstance *aInstance, uint32_t *aMinAge)
|
||||
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
||||
|
||||
bool otBorderRoutingIsMultiAilDetected(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<BorderRouter::MultiAilDetector>().IsDetected();
|
||||
}
|
||||
|
||||
void otBorderRoutingSetMultiAilCallback(otInstance *aInstance,
|
||||
otBorderRoutingMultiAilCallback aCallback,
|
||||
void *aContext)
|
||||
{
|
||||
AsCoreType(aInstance).Get<BorderRouter::MultiAilDetector>().SetCallback(aCallback, aContext);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
|
||||
|
||||
void otBorderRoutingDhcp6PdSetEnabled(otInstance *aInstance, bool aEnabled)
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2025, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file implements the OpenThread Multi-AIL Detection API.
|
||||
*/
|
||||
|
||||
#include <openthread/multi_ail_detection.h>
|
||||
|
||||
#include "instance/instance.hpp"
|
||||
|
||||
using namespace ot;
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
||||
|
||||
void otBorderRoutingSetMultiAilDetectionEnabled(otInstance *aInstance, bool aEnable)
|
||||
{
|
||||
AsCoreType(aInstance).Get<BorderRouter::MultiAilDetector>().SetEnabled(aEnable);
|
||||
}
|
||||
|
||||
bool otBorderRoutingIsMultiAilDetectionEnabled(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<BorderRouter::MultiAilDetector>().IsEnabled();
|
||||
}
|
||||
|
||||
bool otBorderRoutingIsMultiAilDetectionRunning(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<BorderRouter::MultiAilDetector>().IsRunning();
|
||||
}
|
||||
|
||||
bool otBorderRoutingIsMultiAilDetected(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<BorderRouter::MultiAilDetector>().IsDetected();
|
||||
}
|
||||
|
||||
void otBorderRoutingSetMultiAilCallback(otInstance *aInstance,
|
||||
otBorderRoutingMultiAilCallback aCallback,
|
||||
void *aContext)
|
||||
{
|
||||
AsCoreType(aInstance).Get<BorderRouter::MultiAilDetector>().SetCallback(aCallback, aContext);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
||||
@@ -66,7 +66,6 @@ typedef otBorderRoutingPeerBorderRouterEntry PeerBrEntry; ///< Peer Bor
|
||||
typedef otBorderRoutingPrefixTableEntry Dhcp6PdPrefix; ///< DHCPv6 PD prefix.
|
||||
typedef otPdProcessedRaInfo Dhcp6PdCounters; ///< DHCPv6 PD counters.
|
||||
typedef otBorderRoutingRequestDhcp6PdCallback Dhcp6PdCallback; ///< DHCPv6 PD callback.
|
||||
typedef otBorderRoutingMultiAilCallback MultiAilCallback; ///< Multi AIL detection callback.
|
||||
|
||||
// IPv6 Neighbor Discovery (ND) types
|
||||
typedef Ip6::Nd::PrefixInfoOption PrefixInfoOption; ///< Prefix Info Option (PIO).
|
||||
|
||||
@@ -184,6 +184,11 @@ Error InfraIf::HandleStateChanged(uint32_t aIfIndex, bool aIsRunning)
|
||||
mIsRunning = aIsRunning;
|
||||
|
||||
Get<RxRaTracker>().HandleInfraIfStateChanged();
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
||||
Get<MultiAilDetector>().HandleInfraIfStateChanged();
|
||||
#endif
|
||||
|
||||
Get<RoutingManager>().HandleInfraIfStateChanged();
|
||||
|
||||
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
|
||||
|
||||
@@ -40,13 +40,14 @@
|
||||
namespace ot {
|
||||
namespace BorderRouter {
|
||||
|
||||
RegisterLogModule("BorderRouting");
|
||||
RegisterLogModule("MultiAilDetect");
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// MultiAilDetector
|
||||
|
||||
MultiAilDetector::MultiAilDetector(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mState(kAutoEnableMode ? kStateStopped : kStateDisabled)
|
||||
, mDetected(false)
|
||||
, mNetDataPeerBrCount(0)
|
||||
, mReachablePeerBrCount(0)
|
||||
@@ -54,12 +55,88 @@ MultiAilDetector::MultiAilDetector(Instance &aInstance)
|
||||
{
|
||||
}
|
||||
|
||||
void MultiAilDetector::SetEnabled(bool aEnable)
|
||||
{
|
||||
if (aEnable)
|
||||
{
|
||||
VerifyOrExit(mState == kStateDisabled);
|
||||
SetState(kStateStopped);
|
||||
UpdateState();
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(mState != kStateDisabled);
|
||||
Stop();
|
||||
SetState(kStateDisabled);
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void MultiAilDetector::SetState(State aState)
|
||||
{
|
||||
VerifyOrExit(mState != aState);
|
||||
|
||||
LogInfo("State: %s -> %s", StateToString(mState), StateToString(aState));
|
||||
mState = aState;
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void MultiAilDetector::HandleNotifierEvents(ot::Events aEvents)
|
||||
{
|
||||
if (aEvents.Contains(kEventThreadRoleChanged))
|
||||
{
|
||||
UpdateState();
|
||||
}
|
||||
}
|
||||
|
||||
void MultiAilDetector::UpdateState(void)
|
||||
{
|
||||
VerifyOrExit(mState != kStateDisabled);
|
||||
|
||||
if (Get<InfraIf>().IsRunning() && Get<Mle::Mle>().IsAttached())
|
||||
{
|
||||
Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void MultiAilDetector::Start(void)
|
||||
{
|
||||
VerifyOrExit(mState == kStateStopped);
|
||||
|
||||
SetState(kStateRunning);
|
||||
|
||||
Get<RxRaTracker>().SetEnabled(true, RxRaTracker::kRequesterMultiAilDetector);
|
||||
Evaluate();
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void MultiAilDetector::Stop(void)
|
||||
{
|
||||
VerifyOrExit(mState == kStateRunning);
|
||||
|
||||
mTimer.Stop();
|
||||
mDetected = false;
|
||||
mNetDataPeerBrCount = 0;
|
||||
mReachablePeerBrCount = 0;
|
||||
Get<RxRaTracker>().SetEnabled(false, RxRaTracker::kRequesterMultiAilDetector);
|
||||
|
||||
SetState(kStateStopped);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void MultiAilDetector::HandleRxRaTrackerEvents(const RxRaTracker::Events &aEvents)
|
||||
@@ -77,7 +154,7 @@ void MultiAilDetector::Evaluate(void)
|
||||
uint32_t minAge;
|
||||
bool detected;
|
||||
|
||||
VerifyOrExit(Get<RoutingManager>().IsRunning());
|
||||
VerifyOrExit(mState == kStateRunning);
|
||||
|
||||
count = Get<NetDataBrTracker>().CountBrs(NetDataBrTracker::kExcludeThisDevice, minAge);
|
||||
|
||||
@@ -129,6 +206,29 @@ void MultiAilDetector::HandleTimer(void)
|
||||
mCallback.InvokeIfSet(mDetected);
|
||||
}
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
|
||||
|
||||
const char *MultiAilDetector::StateToString(State aState)
|
||||
{
|
||||
static const char *const kStateStrings[] = {
|
||||
"Disabled", // (0) kStateDisabled
|
||||
"Stopped", // (1) kStateStopped
|
||||
"Running", // (2) kStateRunning
|
||||
};
|
||||
|
||||
struct EnumCheck
|
||||
{
|
||||
InitEnumValidatorCounter();
|
||||
ValidateNextEnum(kStateDisabled);
|
||||
ValidateNextEnum(kStateStopped);
|
||||
ValidateNextEnum(kStateRunning);
|
||||
};
|
||||
|
||||
return kStateStrings[aState];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace BorderRouter
|
||||
} // namespace ot
|
||||
|
||||
|
||||
@@ -42,18 +42,21 @@
|
||||
#error "MULTI_AIL_DETECTION_ENABLE feature requires OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE"
|
||||
#endif
|
||||
|
||||
#include <openthread/multi_ail_detection.h>
|
||||
|
||||
#include "border_router/br_types.hpp"
|
||||
#include "border_router/rx_ra_tracker.hpp"
|
||||
#include "common/callback.hpp"
|
||||
#include "common/error.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "common/notifier.hpp"
|
||||
#include "common/timer.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace BorderRouter {
|
||||
|
||||
class InfraIf;
|
||||
class NetDataBrTracker;
|
||||
class RoutingManager;
|
||||
|
||||
/**
|
||||
* Implements Multi-AIL (Adjacent Infrastructure Link) detection.
|
||||
@@ -69,13 +72,52 @@ class RoutingManager;
|
||||
*/
|
||||
class MultiAilDetector : public InstanceLocator
|
||||
{
|
||||
friend class InfraIf;
|
||||
friend class NetDataBrTracker;
|
||||
friend class RxRaTracker;
|
||||
friend class RoutingManager;
|
||||
friend class ot::Notifier;
|
||||
|
||||
public:
|
||||
typedef otBorderRoutingMultiAilCallback MultiAilCallback; ///< Multi AIL detection callback.
|
||||
|
||||
/**
|
||||
* Initializes the `MultiAilDetector`.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
*/
|
||||
explicit MultiAilDetector(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* Enables or disables the Multi-AIL Detector.
|
||||
*
|
||||
* When enabled, the detector starts monitoring the infrastructure interface state and evaluates for multiple AILs.
|
||||
* When disabled, the detector stops and resets its internal state.
|
||||
*
|
||||
* If `OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_AUTO_ENABLE_MODE` is enabled, the detector is enabled
|
||||
* by default and starts running when the infra-if network is initialized and becomes active.
|
||||
*
|
||||
* @param[in] aEnable TRUE to enable the detector, FALSE to disable.
|
||||
*/
|
||||
void SetEnabled(bool aEnable);
|
||||
|
||||
/**
|
||||
* Checks if the Multi-AIL Detector is enabled.
|
||||
*
|
||||
* @retval TRUE If the detector is enabled.
|
||||
* @retval FALSE If the detector is disabled.
|
||||
*/
|
||||
bool IsEnabled(void) const { return mState != kStateDisabled; }
|
||||
|
||||
/**
|
||||
* Checks if the Multi-AIL Detector is running.
|
||||
*
|
||||
* The detector runs when it is enabled and the infrastructure interface is also running.
|
||||
*
|
||||
* @retval TRUE If the detector is running.
|
||||
* @retval FALSE If the detector is not running.
|
||||
*/
|
||||
bool IsRunning(void) const { return mState == kStateRunning; }
|
||||
|
||||
/**
|
||||
* Gets the current detection state regarding multiple Adjacent Infrastructure Links (AILs).
|
||||
*
|
||||
@@ -104,17 +146,37 @@ private:
|
||||
static constexpr uint32_t kDetectTime = 10 * Time::kOneMinuteInMsec;
|
||||
static constexpr uint32_t kClearTime = 1 * Time::kOneMinuteInMsec;
|
||||
|
||||
void Start(void) { Evaluate(); }
|
||||
static constexpr bool kAutoEnableMode = OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_AUTO_ENABLE_MODE;
|
||||
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStateDisabled, // Disabled.
|
||||
kStateStopped, // Enabled but stopped and waiting for `InfraIf` state change.
|
||||
kStateRunning, // Enabled and running.
|
||||
};
|
||||
|
||||
void SetState(State aState);
|
||||
void UpdateState(void);
|
||||
void Start(void);
|
||||
void Stop(void);
|
||||
void Evaluate(void);
|
||||
void HandleTimer(void);
|
||||
|
||||
// Callback from `Notifier`
|
||||
void HandleNotifierEvents(ot::Events aEvents);
|
||||
|
||||
// Callback from `InfraIf`
|
||||
void HandleInfraIfStateChanged(void) { UpdateState(); }
|
||||
|
||||
// Callback from `RxRaTracker`
|
||||
void HandleRxRaTrackerEvents(const RxRaTracker::Events &aEvents);
|
||||
|
||||
static const char *StateToString(State aState);
|
||||
|
||||
using DetectCallback = Callback<MultiAilCallback>;
|
||||
using DetectTimer = TimerMilliIn<MultiAilDetector, &MultiAilDetector::HandleTimer>;
|
||||
|
||||
State mState;
|
||||
bool mDetected;
|
||||
uint16_t mNetDataPeerBrCount;
|
||||
uint16_t mReachablePeerBrCount;
|
||||
|
||||
@@ -265,9 +265,6 @@ void RoutingManager::Start(void)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
||||
mNat64PrefixManager.Start();
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
||||
Get<MultiAilDetector>().Start();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -284,9 +281,6 @@ void RoutingManager::Stop(void)
|
||||
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
||||
mNat64PrefixManager.Stop();
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
||||
Get<MultiAilDetector>().Stop();
|
||||
#endif
|
||||
|
||||
SendRouterAdvertisement(kInvalidateAllPrevPrefixes);
|
||||
|
||||
|
||||
@@ -167,6 +167,9 @@ void Notifier::EmitEvents(void)
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
|
||||
Get<BorderRouter::NetDataBrTracker>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
||||
Get<BorderRouter::MultiAilDetector>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
|
||||
Get<Srp::Client>().HandleNotifierEvents(events);
|
||||
|
||||
@@ -86,13 +86,13 @@
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
||||
*
|
||||
* Define to 1 to enable Routing Manager multiple Adjacent Infrastructure Links (AILs) detection feature.
|
||||
* Define to 1 to enable Multiple Adjacent Infrastructure Links (AILs) detection feature.
|
||||
*
|
||||
* The detection mechanism operates as follows: The Routing Manager monitors the number of peer BRs listed in the
|
||||
* Thread Network Data (see `otBorderRoutingCountPeerBrs()`) and compares this count with the number of peer BRs
|
||||
* discovered by processing received Router Advertisement (RA) messages on its connected AIL. If the count derived from
|
||||
* Network Data consistently exceeds the count derived from RAs for a detection duration of 10 minutes, it concludes
|
||||
* that BRs are likely connected to different AILs. To clear state a shorter window of 1 minute is used.
|
||||
* The detection mechanism operates as follows: The detector monitors the number of peer BRs listed in the Thread
|
||||
* Network Data (see `otBorderRoutingCountPeerBrs()`) and compares this count with the number of peer BRs discovered
|
||||
* by processing received Router Advertisement (RA) messages on its connected AIL. If the count derived from Network
|
||||
* Data consistently exceeds the count derived from RAs for a detection duration of 10 minutes, it concludes that BRs
|
||||
* are likely connected to different AILs. To clear state a shorter window of 1 minute is used.
|
||||
*
|
||||
* See `otBorderRoutingIsMultiAilDetected()` for more details.
|
||||
*/
|
||||
@@ -100,6 +100,20 @@
|
||||
#define OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_AUTO_ENABLE_MODE
|
||||
*
|
||||
* Specifies the "Auto Enable Mode" for Multi-AIL Detection feature.
|
||||
*
|
||||
* When "Auto Enable Mode" is set, the Multi-AIL Detector is enabled by default and starts running and monitoring
|
||||
* when the infrastructure interface network is initialized and become active/running. If this mode is disabled, the
|
||||
* detector will be in a disabled state initially and must be explicitly enabled using the public API
|
||||
* `otBorderRoutingSetMultiAilDetectionEnabled()`.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_AUTO_ENABLE_MODE
|
||||
#define OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_AUTO_ENABLE_MODE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_REACHABILITY_CHECK_ICMP6_ERROR_ENABLE
|
||||
*
|
||||
|
||||
@@ -856,6 +856,9 @@ class Node(object):
|
||||
def br_get_multiail(self):
|
||||
return self._cli_single_output('br multiail')
|
||||
|
||||
def br_get_multiail_state(self):
|
||||
return self.cli('br multiail state')
|
||||
|
||||
def br_get_ifaddrs(self):
|
||||
return self.cli('br ifaddrs')
|
||||
|
||||
|
||||
@@ -36,9 +36,9 @@ import time
|
||||
#
|
||||
# Check multi AIL detection
|
||||
#
|
||||
# -+- _______
|
||||
# | / \
|
||||
# br1 --- br2 --- br3
|
||||
# -+- _________________
|
||||
# | / \ \
|
||||
# br1 --- br2 --- br3 --- detector
|
||||
#
|
||||
|
||||
test_name = __file__[:-3] if __file__.endswith('.py') else __file__
|
||||
@@ -56,6 +56,7 @@ one_minute = 60
|
||||
br1 = cli.Node()
|
||||
br2 = cli.Node()
|
||||
br3 = cli.Node()
|
||||
detector = cli.Node()
|
||||
|
||||
IF_INDEX_1 = 1
|
||||
IF_INDEX_2 = 2
|
||||
@@ -66,10 +67,12 @@ IF_INDEX_2 = 2
|
||||
br1.form("multiail")
|
||||
br2.join(br1)
|
||||
br3.join(br2)
|
||||
detector.join(br2)
|
||||
|
||||
verify(br1.get_state() == 'leader')
|
||||
verify(br2.get_state() == 'router')
|
||||
verify(br3.get_state() == 'router')
|
||||
verify(detector.get_state() == 'router')
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test implementation
|
||||
@@ -86,6 +89,20 @@ time.sleep(one_minute / speedup)
|
||||
verify(br1.br_get_state() == 'running')
|
||||
verify(br1.br_get_multiail() == 'not detected')
|
||||
|
||||
# Init `detector` on different AIL without enabling it as a BR.
|
||||
|
||||
detector.br_init(IF_INDEX_2, 1)
|
||||
time.sleep(10 / speedup)
|
||||
|
||||
# Check that multi-ail detection is auto-enabled and started
|
||||
# on `detector`.
|
||||
|
||||
state = detector.br_get_multiail_state()
|
||||
verify(len(state) == 3)
|
||||
verify(state[0].strip() == 'Enabled: yes')
|
||||
verify(state[1].strip() == 'Running: yes')
|
||||
verify(state[2].strip() == 'Detected: no')
|
||||
|
||||
# Start `br2` and `br3` together on a different AIL
|
||||
|
||||
br2.br_init(IF_INDEX_2, 1)
|
||||
@@ -108,6 +125,7 @@ time.sleep(10.01 * one_minute / speedup)
|
||||
verify(br1.br_get_multiail() == 'detected')
|
||||
verify(br2.br_get_multiail() == 'detected')
|
||||
verify(br3.br_get_multiail() == 'detected')
|
||||
verify(detector.br_get_multiail() == 'detected')
|
||||
|
||||
# Disable `br1`
|
||||
|
||||
@@ -118,8 +136,9 @@ time.sleep(9 * one_minute / speedup)
|
||||
|
||||
verify(br2.br_get_multiail() == 'not detected')
|
||||
verify(br3.br_get_multiail() == 'not detected')
|
||||
verify(detector.br_get_multiail() == 'not detected')
|
||||
|
||||
# Enable `br` again, wait for a short time (before detection) and disable it
|
||||
# Enable `br1` again, wait for a short time (before detection) and disable it
|
||||
|
||||
br1.br_enable()
|
||||
|
||||
@@ -133,6 +152,18 @@ time.sleep(10 * one_minute / speedup)
|
||||
|
||||
verify(br2.br_get_multiail() == 'not detected')
|
||||
verify(br3.br_get_multiail() == 'not detected')
|
||||
verify(detector.br_get_multiail() == 'not detected')
|
||||
|
||||
# `br1` is no longer enabled to act as BR, but its multi-ail detector
|
||||
# should continue to operate and detect that it is on a different AIL.
|
||||
|
||||
verify(br1.br_get_multiail() == 'detected')
|
||||
|
||||
state = br1.br_get_multiail_state()
|
||||
verify(len(state) == 3)
|
||||
verify(state[0].strip() == 'Enabled: yes')
|
||||
verify(state[1].strip() == 'Running: yes')
|
||||
verify(state[2].strip() == 'Detected: yes')
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
@@ -1416,6 +1416,18 @@ void InitTest(bool aEnablBorderRouting = false, bool aAfterReset = false)
|
||||
|
||||
SuccessOrQuit(otIp6SetEnabled(sInstance, true));
|
||||
SuccessOrQuit(otThreadSetEnabled(sInstance, true));
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
||||
// We explicitly disable the multi-AIL detector to prevent
|
||||
// interference with the tests. The detector enables
|
||||
// `RxRaTracker` and keeps it enabled even when Border Routing is
|
||||
// disabled, which keeps prefix entries in the heap and can
|
||||
// invalidate the heap allocation checks. It may also mess up the
|
||||
// expected timing of RS (Router Solicitation) messages (starting
|
||||
// the `RxRaTracker` early).
|
||||
otBorderRoutingSetMultiAilDetectionEnabled(sInstance, false);
|
||||
#endif
|
||||
|
||||
SuccessOrQuit(otBorderRoutingSetEnabled(sInstance, aEnablBorderRouting));
|
||||
|
||||
// Reset all test flags
|
||||
|
||||
Reference in New Issue
Block a user