mirror of
https://github.com/espressif/openthread.git
synced 2026-06-05 21:14:49 +00:00
[border-agent] implement Border Admitter (#12201)
This commit introduces the Border Agent Admitter feature , which enhances Thread MeshCoP. A Border Admitter is an enhanced Border Agent that functions as a traditional BA while enabling new behaviors. It acts as a proxy and dispatcher, allowing multiple external Enrollers to connect to it. It then petitions to become the single Active Commissioner on the Thread mesh, forwards new joiner requests to connected Enrollers, and manages the session between joiners and multiple Enrollers The implementation includes three main components: - `Admitter`: The main class that orchestrates the feature, managing enroller sessions and aggregating steering data. - `Arbitrator`: A distributed election mechanism that runs among Border Admitters on the mesh to select a single "Prime Admitter" by publishing a new Border Admitter service in the Thread Network Data. - `CommissionerPetitioner`: A sub-component responsible for petitioning the Leader to be granted the commissioner role. It handles conflicts if another commissioner is already active. New public APIs are added in `openthread/border_agent_admitter.h`. This commit also introduces a suite of comprehensive tests for the Border Admitter functionality under the `nexus` test framework. It covers various scenarios including: - Prime Admitter election and role management - Enroller registration, keep-alive, and timeout interactions - Handling of commissioner conflicts and petitioner retry mechanisms - Support for multiple enroller sessions and combined steering data - Forwarding of Joiner `RelayRx` and `UdpProxy` messages - Joiner acceptance, release, and expiration tracking
This commit is contained in:
committed by
GitHub
parent
e4ffaf347f
commit
66c7272eef
@@ -173,6 +173,7 @@ ot_option(OT_BACKBONE_ROUTER OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE "backbone
|
||||
ot_option(OT_BACKBONE_ROUTER_DUA_NDPROXYING OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE "BBR DUA ND Proxy")
|
||||
ot_option(OT_BACKBONE_ROUTER_MULTICAST_ROUTING OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE "BBR MR")
|
||||
ot_option(OT_BLE_TCAT OPENTHREAD_CONFIG_BLE_TCAT_ENABLE "Ble based thread commissioning")
|
||||
ot_option(OT_BORDER_ADMITTER OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE "border agent admitter")
|
||||
ot_option(OT_BORDER_AGENT OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE "border agent")
|
||||
ot_option(OT_BORDER_AGENT_EPSKC OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE "border agent ephemeral PSKc")
|
||||
ot_option(OT_BORDER_AGENT_ID OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE "create and save border agent ID")
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#define OPENTHREAD_CONFIG_ASSERT_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE 1
|
||||
|
||||
@@ -43,6 +43,7 @@ source_set("openthread") {
|
||||
"backbone_router_ftd.h",
|
||||
"ble_secure.h",
|
||||
"border_agent.h",
|
||||
"border_agent_admitter.h",
|
||||
"border_agent_ephemeral_key.h",
|
||||
"border_agent_tracker.h",
|
||||
"border_agent_txt_data.h",
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* 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 includes functions for the Thread Border Agent Admitter.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_BORDER_AGENT_ADMITTER_H_
|
||||
#define OPENTHREAD_BORDER_AGENT_ADMITTER_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread/border_agent.h>
|
||||
#include <openthread/error.h>
|
||||
#include <openthread/instance.h>
|
||||
#include <openthread/ip6.h>
|
||||
#include <openthread/steering_data.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup api-border-agent
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions for the Thread Border Agent Admitter role.
|
||||
*
|
||||
* All APIs in this module require both `OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE` and
|
||||
* `OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE` features to be enabled.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents an iterator for Border Admitter enroller.
|
||||
*
|
||||
* The caller MUST NOT access or update the fields in this struct. It is intended for OpenThread internal use only.
|
||||
*/
|
||||
typedef struct otBorderAdmitterIterator
|
||||
{
|
||||
void *mPtr1;
|
||||
void *mPtr2;
|
||||
uint64_t mData1;
|
||||
uint32_t mData2;
|
||||
} otBorderAdmitterIterator;
|
||||
|
||||
/**
|
||||
* Represents information about an enroller.
|
||||
*
|
||||
* To ensure consistent `mRegisterDuration` calculations, the iterator's initialization time is stored within the
|
||||
* iterator, and each enroller `mRegisterDuration` is calculated relative to this time.
|
||||
*/
|
||||
typedef struct otBorderAdmitterEnrollerInfo
|
||||
{
|
||||
otBorderAgentSessionInfo mSessionInfo; ///< The session information.
|
||||
const char *mId; ///< The enroller ID string.
|
||||
otSteeringData mSteeringData; ///< The steering data.
|
||||
uint8_t mMode; ///< The enroller's mode.
|
||||
uint64_t mRegisterDuration; ///< Milliseconds since the enroller registered.
|
||||
} otBorderAdmitterEnrollerInfo;
|
||||
|
||||
/**
|
||||
* Represents information about a joiner accepted by an enroller.
|
||||
*
|
||||
* To ensure consistent duration calculations, the iterator's initialization time is stored within the iterator, and
|
||||
* the `mMsecSinceAccept` is calculated relative to this time.
|
||||
*/
|
||||
typedef struct otBorderAdmitterJoinerInfo
|
||||
{
|
||||
otIp6InterfaceIdentifier mIid; ///< Joiner IID.
|
||||
uint64_t mMsecSinceAccept; ///< Milliseconds since the joiner was accepted by the enroller.
|
||||
uint32_t mMsecTillExpiration; ///< Milliseconds till the joiner will be expired and removed.
|
||||
} otBorderAdmitterJoinerInfo;
|
||||
|
||||
/**
|
||||
* Enables or disables the Border Agent Admitter.
|
||||
*
|
||||
* The default enable/disable state of Border Admitter (after OpenThread stack initialization) is determined by the
|
||||
* OpenThread config `OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLED_BY_DEFAULT`.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
* @param[in] aEnabled A boolean to indicate whether to enable (TRUE) or disable (FALSE) the Border Agent Admitter.
|
||||
*/
|
||||
void otBorderAdmitterSetEnabled(otInstance *aInstance, bool aEnable);
|
||||
|
||||
/**
|
||||
* Indicates whether the Border Agent Admitter is enabled.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
*
|
||||
* @retval TRUE The Border Agent Admitter is enabled.
|
||||
* @retval FALSE The Border Agent Admitter is disabled.
|
||||
*/
|
||||
bool otBorderAdmitterIsEnabled(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Indicates whether the device is currently the Prime Admitter.
|
||||
*
|
||||
* The Prime Admitter is the device that wins the election among all Admitters within the Thread mesh network. The
|
||||
* election algorithm ensures convergence on a single Prime Admitter within the mesh.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
*
|
||||
* @retval TRUE This device is the Prime Admitter.
|
||||
* @retval FALSE This device is not the Prime Admitter.
|
||||
*/
|
||||
bool otBorderAdmitterIsPrimeAdmitter(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Indicates whether the Prime Admitter is currently the active commissioner.
|
||||
*
|
||||
* After becoming the Prime Admitter and having at least one enroller register, the Admitter petitions the Leader to
|
||||
* be granted the commissioner role.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
*
|
||||
* @retval TRUE This device is the active commissioner.
|
||||
* @retval FALSE This device is not the active commissioner.
|
||||
*/
|
||||
bool otBorderAdmitterIsActiveCommissioner(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Indicates whether the Prime Admitter's petition to become the native mesh commissioner was rejected.
|
||||
*
|
||||
* A rejection typically occurs if there is already another active commissioner in the Thread network.
|
||||
*
|
||||
* The Admitter will automatically retry petitioning. It monitors the Thread Network Data to see when the other
|
||||
* commissioner is removed and retry its own petition.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
*
|
||||
* @retval TRUE The petition was rejected.
|
||||
* @retval FALSE The petition was not rejected.
|
||||
*/
|
||||
bool otBorderAdmitterIsPetitionRejected(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Gets the Joiner UDP port.
|
||||
*
|
||||
* A zero value indicates the Joiner UDP port is not specified/fixed by the Admitter (Joiner Routers can pick).
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
*
|
||||
* @returns The joiner UDP port number.
|
||||
*/
|
||||
uint16_t otBorderAdmitterGetJoinerUdpPort(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Sets the joiner UDP port.
|
||||
*
|
||||
* A zero value indicates the Joiner UDP port is not specified/fixed by the Admitter (Joiner Routers can pick).
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
* @param[in] aUdpPort The joiner UDP port number.
|
||||
*/
|
||||
void otBorderAdmitterSetJoinerUdpPort(otInstance *aInstance, uint16_t aUdpPort);
|
||||
|
||||
/**
|
||||
* Initializes an `otBorderAdmitterIterator`.
|
||||
*
|
||||
* An iterator MUST be initialized before it is used.
|
||||
*
|
||||
* An iterator can be initialized again to restart from the beginning of the list.
|
||||
*
|
||||
* When iterating over enrollers, the initialization time is recorded and used to calculate a consistent
|
||||
* `mRegisterDuration` for each enroller.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aIterator A pointer to the iterator to initialize.
|
||||
*
|
||||
*/
|
||||
void otBorderAdmitterInitIterator(otInstance *aInstance, otBorderAdmitterIterator *aIterator);
|
||||
|
||||
/**
|
||||
* Retrieves the information about the next Enroller registered with the Admitter.
|
||||
*
|
||||
* @param[in] aIterator The iterator to use.
|
||||
* @param[out] aEnrollerInfo A pointer to an `otBorderAdmitterEnrollerInfo` to populate.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully retrieved the next enroller info.
|
||||
* @retval OT_ERROR_NOT_FOUND No more enrollers are available. The end of the list has been reached.
|
||||
*/
|
||||
otError otBorderAdmitterGetNextEnrollerInfo(otBorderAdmitterIterator *aIterator,
|
||||
otBorderAdmitterEnrollerInfo *aEnrollerInfo);
|
||||
|
||||
/**
|
||||
* Retrieves the information about the next accepted joiner by the latest retrieved enroller during iteration.
|
||||
*
|
||||
* Iterates over all joiners which are accepted by the latest enroller, i.e., the last enroller which was retrieved
|
||||
* using the @p aIterator along with `otBorderAdmitterGetNextEnrollerInfo()`.
|
||||
*
|
||||
* @param[in] aIterator The iterator to use.
|
||||
* @param[out] aJoinerInfo A pointer to an `otBorderAdmitterJoinerInfo` to populate.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully retrieved the next joiner info.
|
||||
* @retval OT_ERROR_NOT_FOUND No more joiners are available. The end of the list has been reached.
|
||||
*/
|
||||
otError otBorderAdmitterGetNextJoinerInfo(otBorderAdmitterIterator *aIterator, otBorderAdmitterJoinerInfo *aJoinerInfo);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_BORDER_AGENT_ADMITTER_H_
|
||||
@@ -119,14 +119,15 @@ typedef enum otBorderAgentMultiAilState
|
||||
*/
|
||||
typedef struct otBorderAgentStateBitmap
|
||||
{
|
||||
otBorderAgentConnMode mConnMode; ///< Connection Mode.
|
||||
otBorderAgentThreadIfState mThreadIfState; ///< Thread Interface Status.
|
||||
otBorderAgentAvailability mAvailability; ///< Availability
|
||||
otBorderAgentThreadRole mThreadRole; ///< Thread Role.
|
||||
bool mBbrIsActive; ///< Backbone Router function is active.
|
||||
bool mBbrIsPrimary; ///< Device is the Primary Backbone Router.
|
||||
bool mEpskcSupported; ///< ePSKc Mode is supported.
|
||||
otBorderAgentMultiAilState mMultiAilState; ///< Multi-AIL detection state.
|
||||
otBorderAgentConnMode mConnMode; ///< Connection Mode.
|
||||
otBorderAgentThreadIfState mThreadIfState; ///< Thread Interface Status.
|
||||
otBorderAgentAvailability mAvailability; ///< Availability
|
||||
otBorderAgentThreadRole mThreadRole; ///< Thread Role.
|
||||
bool mBbrIsActive; ///< Backbone Router function is active.
|
||||
bool mBbrIsPrimary; ///< Device is the Primary Backbone Router.
|
||||
bool mEpskcSupported; ///< ePSKc Mode is supported.
|
||||
otBorderAgentMultiAilState mMultiAilState; ///< Multi-AIL detection state.
|
||||
bool mAdmitterSupported; ///< Border Admitter function is supported.
|
||||
} otBorderAgentStateBitmap;
|
||||
|
||||
/**
|
||||
|
||||
@@ -304,6 +304,9 @@ typedef enum otMeshcopTlvType
|
||||
OT_MESHCOP_TLV_ENERGY_LIST = 57, ///< meshcop Energy List TLV
|
||||
OT_MESHCOP_TLV_THREAD_DOMAIN_NAME = 59, ///< meshcop Thread Domain Name TLV
|
||||
OT_MESHCOP_TLV_WAKEUP_CHANNEL = 74, ///< meshcop Wake-up Channel TLV
|
||||
OT_MESHCOP_TLV_ADMITTER_STATE = 90, ///< meshcop Admitter State TLV
|
||||
OT_MESHCOP_TLV_ENROLLER_ID = 91, ///< meshcop Enroller ID TLV
|
||||
OT_MESHCOP_TLV_ENROLLER_MODE = 92, ///< meshcop Enroller Mode TLV
|
||||
OT_MESHCOP_TLV_DISCOVERYREQUEST = 128, ///< meshcop Discovery Request TLV
|
||||
OT_MESHCOP_TLV_DISCOVERYRESPONSE = 129, ///< meshcop Discovery Response TLV
|
||||
OT_MESHCOP_TLV_JOINERADVERTISEMENT = 241, ///< meshcop Joiner Advertisement TLV (experimental)
|
||||
|
||||
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (577)
|
||||
#define OPENTHREAD_API_VERSION (578)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -324,6 +324,7 @@ openthread_core_files = [
|
||||
"api/backbone_router_api.cpp",
|
||||
"api/backbone_router_ftd_api.cpp",
|
||||
"api/ble_secure_api.cpp",
|
||||
"api/border_agent_admitter_api.cpp",
|
||||
"api/border_agent_api.cpp",
|
||||
"api/border_agent_ephemeral_key_api.cpp",
|
||||
"api/border_agent_tracker_api.cpp",
|
||||
@@ -551,6 +552,8 @@ openthread_core_files = [
|
||||
"meshcop/announce_begin_client.hpp",
|
||||
"meshcop/border_agent.cpp",
|
||||
"meshcop/border_agent.hpp",
|
||||
"meshcop/border_agent_admitter.cpp",
|
||||
"meshcop/border_agent_admitter.hpp",
|
||||
"meshcop/border_agent_ephemeral_key.cpp",
|
||||
"meshcop/border_agent_ephemeral_key.hpp",
|
||||
"meshcop/border_agent_tracker.cpp",
|
||||
@@ -874,6 +877,7 @@ source_set("libopenthread_core_config") {
|
||||
"config/announce_sender.h",
|
||||
"config/backbone_router.h",
|
||||
"config/border_agent.h",
|
||||
"config/border_agent_admitter.h",
|
||||
"config/border_router.h",
|
||||
"config/border_routing.h",
|
||||
"config/channel_manager.h",
|
||||
|
||||
@@ -34,6 +34,7 @@ set(COMMON_SOURCES
|
||||
api/backbone_router_api.cpp
|
||||
api/backbone_router_ftd_api.cpp
|
||||
api/ble_secure_api.cpp
|
||||
api/border_agent_admitter_api.cpp
|
||||
api/border_agent_api.cpp
|
||||
api/border_agent_ephemeral_key_api.cpp
|
||||
api/border_agent_tracker_api.cpp
|
||||
@@ -164,6 +165,7 @@ set(COMMON_SOURCES
|
||||
mac/wakeup_tx_scheduler.cpp
|
||||
meshcop/announce_begin_client.cpp
|
||||
meshcop/border_agent.cpp
|
||||
meshcop/border_agent_admitter.cpp
|
||||
meshcop/border_agent_ephemeral_key.cpp
|
||||
meshcop/border_agent_tracker.cpp
|
||||
meshcop/border_agent_txt_data.cpp
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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
|
||||
* This file implements the OpenThread Border Agent Admitter API.
|
||||
*/
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
|
||||
#include <openthread/border_agent_admitter.h>
|
||||
|
||||
#include "instance/instance.hpp"
|
||||
|
||||
using namespace ot;
|
||||
|
||||
void otBorderAdmitterSetEnabled(otInstance *aInstance, bool aEnable)
|
||||
{
|
||||
AsCoreType(aInstance).Get<MeshCoP::BorderAgent::Admitter>().SetEnabled(aEnable);
|
||||
}
|
||||
|
||||
bool otBorderAdmitterIsEnabled(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent::Admitter>().IsEnabled();
|
||||
}
|
||||
|
||||
bool otBorderAdmitterIsPrimeAdmitter(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent::Admitter>().IsPrimeAdmitter();
|
||||
}
|
||||
|
||||
bool otBorderAdmitterIsActiveCommissioner(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent::Admitter>().IsActiveCommissioner();
|
||||
}
|
||||
|
||||
bool otBorderAdmitterIsPetitionRejected(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent::Admitter>().IsPetitionRejected();
|
||||
}
|
||||
|
||||
uint16_t otBorderAdmitterGetJoinerUdpPort(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent::Admitter>().GetJoinerUdpPort();
|
||||
}
|
||||
|
||||
void otBorderAdmitterSetJoinerUdpPort(otInstance *aInstance, uint16_t aUdpPort)
|
||||
{
|
||||
AsCoreType(aInstance).Get<MeshCoP::BorderAgent::Admitter>().SetJoinerUdpPort(aUdpPort);
|
||||
}
|
||||
|
||||
void otBorderAdmitterInitIterator(otInstance *aInstance, otBorderAdmitterIterator *aIterator)
|
||||
{
|
||||
AsCoreType(aIterator).Init(AsCoreType(aInstance));
|
||||
}
|
||||
|
||||
otError otBorderAdmitterGetNextEnrollerInfo(otBorderAdmitterIterator *aIterator,
|
||||
otBorderAdmitterEnrollerInfo *aEnrollerInfo)
|
||||
{
|
||||
AssertPointerIsNotNull(aEnrollerInfo);
|
||||
|
||||
return AsCoreType(aIterator).GetNextEnrollerInfo(*aEnrollerInfo);
|
||||
}
|
||||
|
||||
otError otBorderAdmitterGetNextJoinerInfo(otBorderAdmitterIterator *aIterator, otBorderAdmitterJoinerInfo *aJoinerInfo)
|
||||
{
|
||||
AssertPointerIsNotNull(aJoinerInfo);
|
||||
|
||||
return AsCoreType(aIterator).GetNextJoinerInfo(*aJoinerInfo);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
@@ -134,6 +134,9 @@ void Notifier::EmitEvents(void)
|
||||
Get<MeshCoP::BorderAgent::Manager>().HandleNotifierEvents(events);
|
||||
Get<MeshCoP::BorderAgent::TxtData>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
Get<MeshCoP::BorderAgent::Admitter>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
|
||||
Get<MlrManager>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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
|
||||
* This file includes compile-time configurations for the Border Agent Admitter.
|
||||
*/
|
||||
|
||||
#ifndef OT_CORE_CONFIG_BORDER_AGENT_ADMITTER_H_
|
||||
#define OT_CORE_CONFIG_BORDER_AGENT_ADMITTER_H_
|
||||
|
||||
/**
|
||||
* @addtogroup config-border-agent
|
||||
*
|
||||
* @brief
|
||||
* This module includes configuration variables for the Border Agent Admitter.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
*
|
||||
* Define to 1 to enable Border Agent's Admitter feature.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLED_BY_DEFAULT
|
||||
*
|
||||
* Define to 1 to enable the Border Admitter by default upon OpenThread stack initialization.
|
||||
*
|
||||
* Applicable when `OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE` is enabled.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLED_BY_DEFAULT
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLED_BY_DEFAULT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_DEFAULT_JOINER_UDP_PORT
|
||||
*
|
||||
* Specifies the default Joiner UDP port used by the Border Admitter.
|
||||
*
|
||||
* A value of zero indicates that the Joiner UDP port is not specified/fixed by the Admitter, allowing Joiner Routers
|
||||
* to pick.
|
||||
*
|
||||
* Applicable when `OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE` is enabled.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_DEFAULT_JOINER_UDP_PORT
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_DEFAULT_JOINER_UDP_PORT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // OT_CORE_CONFIG_BORDER_AGENT_ADMITTER_H_
|
||||
@@ -175,6 +175,9 @@ Instance::Instance(void)
|
||||
, mBorderAgentTxtData(*this)
|
||||
, mBorderAgentManager(*this)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
, mBorderAgentAdmitter(*this)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
|
||||
, mBorderAgentEphemeralKeyManager(*this)
|
||||
#endif
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
#include "mac/mac.hpp"
|
||||
#include "mac/wakeup_tx_scheduler.hpp"
|
||||
#include "meshcop/border_agent.hpp"
|
||||
#include "meshcop/border_agent_admitter.hpp"
|
||||
#include "meshcop/border_agent_ephemeral_key.hpp"
|
||||
#include "meshcop/border_agent_tracker.hpp"
|
||||
#include "meshcop/border_agent_txt_data.hpp"
|
||||
@@ -602,6 +603,10 @@ private:
|
||||
MeshCoP::BorderAgent::Manager mBorderAgentManager;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
MeshCoP::BorderAgent::Admitter mBorderAgentAdmitter;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
|
||||
MeshCoP::BorderAgent::EphemeralKeyManager mBorderAgentEphemeralKeyManager;
|
||||
#endif
|
||||
@@ -1073,6 +1078,10 @@ template <> inline MeshCoP::BorderAgent::Manager &Instance::Get(void) { return m
|
||||
template <> inline MeshCoP::BorderAgent::TxtData &Instance::Get(void) { return mBorderAgentTxtData; }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
template <> inline MeshCoP::BorderAgent::Admitter &Instance::Get(void) { return mBorderAgentAdmitter; }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
|
||||
template <> inline MeshCoP::BorderAgent::EphemeralKeyManager &Instance::Get(void)
|
||||
{
|
||||
|
||||
@@ -48,8 +48,15 @@ RegisterLogModule("BorderAgent");
|
||||
// `Manager`
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
|
||||
|
||||
const char Manager::kServiceType[] = "_meshcop._udp";
|
||||
const char Manager::kDefaultBaseServiceName[] = OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_BASE_NAME;
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
const char Manager::kAdmitterSubType[] = "_admitter";
|
||||
const char *const Manager::kServiceSubTypes[] = {kAdmitterSubType};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Manager::Manager(Instance &aInstance)
|
||||
@@ -171,6 +178,10 @@ void Manager::Start(void)
|
||||
|
||||
Get<TxtData>().Refresh();
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
Get<Admitter>().EvaluateOperation();
|
||||
#endif
|
||||
|
||||
exit:
|
||||
if (!mIsRunning)
|
||||
{
|
||||
@@ -196,6 +207,10 @@ void Manager::Stop(void)
|
||||
|
||||
Get<TxtData>().Refresh();
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
Get<Admitter>().EvaluateOperation();
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
@@ -364,6 +379,10 @@ template <> void Manager::HandleTmf<kUriRelayRx>(Coap::Msg &aMsg)
|
||||
|
||||
LogInfo("Received %s from %s", UriToString<kUriRelayRx>(), aMsg.mMessageInfo.GetPeerAddr().ToString().AsCString());
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
Get<Admitter>().ForwardJoinerRelayToEnrollers(aMsg);
|
||||
#endif
|
||||
|
||||
VerifyOrExit(mCommissionerSession != nullptr);
|
||||
mCommissionerSession->ForwardUdpRelayToCommissioner(aMsg.mMessage);
|
||||
|
||||
@@ -446,6 +465,14 @@ void Manager::RegisterService(void)
|
||||
service.mTxtData = txtDataBuffer;
|
||||
service.mTxtDataLength = txtDataLength;
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
if (Get<Admitter>().IsPrimeAdmitter())
|
||||
{
|
||||
service.mSubTypeLabels = kServiceSubTypes;
|
||||
service.mSubTypeLabelsLength = GetArrayLength(kServiceSubTypes);
|
||||
}
|
||||
#endif
|
||||
|
||||
Get<Dnssd>().RegisterService(service, /* aRequestId */ 0, /* aCallback */ nullptr);
|
||||
|
||||
Heap::Free(txtDataBuffer);
|
||||
@@ -520,12 +547,7 @@ Error Manager::SessionIterator::GetNextSessionInfo(SessionInfo &aSessionInfo)
|
||||
VerifyOrExit(session != nullptr, error = kErrorNotFound);
|
||||
|
||||
SetSession(static_cast<CoapDtlsSession *>(session->GetNext()));
|
||||
|
||||
aSessionInfo.mPeerSockAddr.mAddress = session->GetMessageInfo().GetPeerAddr();
|
||||
aSessionInfo.mPeerSockAddr.mPort = session->GetMessageInfo().GetPeerPort();
|
||||
aSessionInfo.mIsConnected = session->IsConnected();
|
||||
aSessionInfo.mIsCommissioner = session->IsActiveCommissioner();
|
||||
aSessionInfo.mLifetime = GetInitTime() - session->GetAllocationTime();
|
||||
session->CopyInfoTo(aSessionInfo, GetInitTime());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -573,6 +595,10 @@ void Manager::CoapDtlsSession::Cleanup(void)
|
||||
|
||||
Get<Manager>().RevokeRoleIfActiveCommissioner(*this);
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
ResignEnroller();
|
||||
#endif
|
||||
|
||||
Coap::SecureSession::Cleanup();
|
||||
}
|
||||
|
||||
@@ -607,6 +633,15 @@ bool Manager::CoapDtlsSession::HandleResource(const char *aUriPath, Coap::Msg &a
|
||||
case kUriProxyTx:
|
||||
HandleTmfProxyTx(aMsg);
|
||||
break;
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
case kUriEnrollerRegister:
|
||||
case kUriEnrollerKeepAlive:
|
||||
case kUriEnrollerJoinerAccept:
|
||||
case kUriEnrollerJoinerRelease:
|
||||
HandleEnrollerTmf(uri, aMsg);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
didHandle = false;
|
||||
break;
|
||||
@@ -631,6 +666,9 @@ void Manager::CoapDtlsSession::HandleConnected(ConnectEvent aEvent)
|
||||
else
|
||||
{
|
||||
LogInfo("Session %u disconnected", mIndex);
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
ResignEnroller();
|
||||
#endif
|
||||
Get<Manager>().HandleSessionDisconnected(*this, aEvent);
|
||||
}
|
||||
}
|
||||
@@ -817,6 +855,17 @@ exit:
|
||||
|
||||
void Manager::CoapDtlsSession::ForwardUdpProxyToCommissioner(const Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = ForwardUdpProxy(aMessage, aMessageInfo));
|
||||
Log<kUriProxyRx>(kForward);
|
||||
|
||||
exit:
|
||||
LogWarnOnError(error, "forward UDP proxy");
|
||||
}
|
||||
|
||||
Error Manager::CoapDtlsSession::ForwardUdpProxy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
OwnedPtr<Coap::Message> message;
|
||||
@@ -843,15 +892,24 @@ void Manager::CoapDtlsSession::ForwardUdpProxyToCommissioner(const Message
|
||||
|
||||
SuccessOrExit(error = Tlv::Append<Ip6AddressTlv>(*message, aMessageInfo.GetPeerAddr()));
|
||||
|
||||
SuccessOrExit(error = SendMessage(message.PassOwnership()));
|
||||
|
||||
Log<kUriProxyRx>(kForward);
|
||||
error = SendMessage(message.PassOwnership());
|
||||
|
||||
exit:
|
||||
LogWarnOnError(error, "forward UDP proxy");
|
||||
return error;
|
||||
}
|
||||
|
||||
void Manager::CoapDtlsSession::ForwardUdpRelayToCommissioner(const Message &aMessage)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = ForwardUdpRelay(aMessage));
|
||||
Log<kUriRelayRx>(kForward);
|
||||
|
||||
exit:
|
||||
LogWarnOnError(error, "forward UDP relay");
|
||||
}
|
||||
|
||||
Error Manager::CoapDtlsSession::ForwardUdpRelay(const Message &aMessage)
|
||||
{
|
||||
OwnedPtr<Coap::Message> forwardMessage;
|
||||
Error error = kErrorNone;
|
||||
@@ -859,12 +917,10 @@ void Manager::CoapDtlsSession::ForwardUdpRelayToCommissioner(const Message &aMes
|
||||
forwardMessage.Reset(NewPriorityNonConfirmablePostMessage(kUriRelayRx));
|
||||
VerifyOrExit(forwardMessage != nullptr, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = ForwardToCommissioner(forwardMessage.PassOwnership(), aMessage));
|
||||
|
||||
Log<kUriRelayRx>(kForward);
|
||||
error = ForwardToCommissioner(forwardMessage.PassOwnership(), aMessage);
|
||||
|
||||
exit:
|
||||
LogWarnOnError(error, "forward UDP relay");
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Manager::CoapDtlsSession::ForwardToCommissioner(OwnedPtr<Coap::Message> aForwardMessage, const Message &aMessage)
|
||||
@@ -911,7 +967,18 @@ void Manager::CoapDtlsSession::HandleTmfProxyTx(Coap::Msg &aMsg)
|
||||
|
||||
Log<kUriProxyTx>(kReceive);
|
||||
|
||||
VerifyOrExit(IsActiveCommissioner(), error = kErrorInvalidState);
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
if (IsEnroller())
|
||||
{
|
||||
VerifyOrExit(Get<Admitter>().IsActiveCommissioner(), error = kErrorInvalidState);
|
||||
messageInfo.SetSockAddr(Get<Admitter>().mCommissionerPetitioner.GetAloc());
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
VerifyOrExit(IsActiveCommissioner(), error = kErrorInvalidState);
|
||||
messageInfo.SetSockAddr(Get<Manager>().GetCommissionerAloc());
|
||||
}
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMsg.mMessage, Tlv::kUdpEncapsulation, offsetRange));
|
||||
|
||||
@@ -926,7 +993,6 @@ void Manager::CoapDtlsSession::HandleTmfProxyTx(Coap::Msg &aMsg)
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMsg.mMessage, offsetRange));
|
||||
|
||||
messageInfo.SetSockPort(udpEncapHeader.GetSourcePort());
|
||||
messageInfo.SetSockAddr(Get<Manager>().GetCommissionerAloc());
|
||||
messageInfo.SetPeerPort(udpEncapHeader.GetDestinationPort());
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<Ip6AddressTlv>(aMsg.mMessage, messageInfo.GetPeerAddr()));
|
||||
@@ -951,7 +1017,16 @@ void Manager::CoapDtlsSession::HandleTmfRelayTx(Coap::Msg &aMsg)
|
||||
|
||||
VerifyOrExit(aMsg.IsNonConfirmablePostRequest());
|
||||
|
||||
VerifyOrExit(IsActiveCommissioner(), error = kErrorInvalidState);
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
if (IsEnroller())
|
||||
{
|
||||
VerifyOrExit(Get<Admitter>().IsActiveCommissioner(), error = kErrorInvalidState);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
VerifyOrExit(IsActiveCommissioner(), error = kErrorInvalidState);
|
||||
}
|
||||
|
||||
Log<kUriRelayTx>(kReceive);
|
||||
|
||||
@@ -1052,11 +1127,23 @@ void Manager::CoapDtlsSession::HandleTimer(void)
|
||||
{
|
||||
if (IsConnected())
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
ResignEnroller();
|
||||
#endif
|
||||
LogInfo("Session %u timed out - disconnecting", mIndex);
|
||||
DisconnectTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::CoapDtlsSession::CopyInfoTo(SessionInfo &aInfo, UptimeMsec aUptimeNow) const
|
||||
{
|
||||
aInfo.mPeerSockAddr.mAddress = GetMessageInfo().GetPeerAddr();
|
||||
aInfo.mPeerSockAddr.mPort = GetMessageInfo().GetPeerPort();
|
||||
aInfo.mIsConnected = IsConnected();
|
||||
aInfo.mIsCommissioner = IsActiveCommissioner();
|
||||
aInfo.mLifetime = aUptimeNow - GetAllocationTime();
|
||||
}
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
|
||||
|
||||
void Manager::CoapDtlsSession::LogUri(Action aAction, const char *aUriString, const char *aTxt)
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "common/owned_ptr.hpp"
|
||||
#include "common/tasklet.hpp"
|
||||
#include "common/uptime.hpp"
|
||||
#include "meshcop/border_agent_admitter.hpp"
|
||||
#include "meshcop/border_agent_txt_data.hpp"
|
||||
#include "meshcop/dataset.hpp"
|
||||
#include "meshcop/secure_transport.hpp"
|
||||
@@ -109,6 +110,9 @@ class Manager : public InstanceLocator, private NonCopyable
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
|
||||
friend class EphemeralKeyManager;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
friend class Admitter;
|
||||
#endif
|
||||
friend class ot::Notifier;
|
||||
friend class Tmf::Agent;
|
||||
@@ -270,6 +274,9 @@ private:
|
||||
class CoapDtlsSession : public Coap::SecureSession, public Heap::Allocatable<CoapDtlsSession>
|
||||
{
|
||||
friend Heap::Allocatable<CoapDtlsSession>;
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
friend class Admitter;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Error SendMessage(OwnedPtr<Coap::Message> aMessage);
|
||||
@@ -279,6 +286,7 @@ private:
|
||||
bool IsActiveCommissioner(void) const;
|
||||
uint64_t GetAllocationTime(void) const { return mAllocationTime; }
|
||||
uint16_t GetIndex(void) const { return mIndex; }
|
||||
void CopyInfoTo(SessionInfo &aInfo, UptimeMsec aUptimeNow) const;
|
||||
|
||||
private:
|
||||
enum Action : uint8_t
|
||||
@@ -303,6 +311,8 @@ private:
|
||||
CoapDtlsSession(Instance &aInstance, Dtls::Transport &aDtlsTransport);
|
||||
|
||||
Error ForwardToCommissioner(OwnedPtr<Coap::Message> aForwardMessage, const Message &aMessage);
|
||||
Error ForwardUdpRelay(const Message &aMessage);
|
||||
Error ForwardUdpProxy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void HandleTmfCommissionerKeepAlive(Coap::Msg &aMsg);
|
||||
void HandleTmfRelayTx(Coap::Msg &aMsg);
|
||||
void HandleTmfProxyTx(Coap::Msg &aMsg);
|
||||
@@ -321,6 +331,23 @@ private:
|
||||
static void HandleTimer(Timer &aTimer);
|
||||
void HandleTimer(void);
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
bool IsEnroller(void) const { return mEnroller != nullptr; }
|
||||
void ResignEnroller(void);
|
||||
void HandleEnrollerTmf(Uri aUri, const Coap::Msg &aMsg);
|
||||
Error ProcessEnrollerRegister(const Coap::Message &aMessage);
|
||||
Error ProcessEnrollerKeepAlive(const Coap::Message &aMessage);
|
||||
Error ProcessEnrollerJoinerAccept(const Coap::Message &aMessage);
|
||||
Error ProcessEnrollerJoinerRelease(const Coap::Message &aMessage);
|
||||
void SendEnrollerResponse(Uri aUri, StateTlv::State aResponseState, const Coap::Message &aRequest);
|
||||
void SendEnrollerReportState(uint8_t aAdmitterState);
|
||||
Error AppendAdmitterTlvs(Coap::Message &aMessage, uint8_t aAdmitterState);
|
||||
void ForwardUdpRelayToEnroller(const Coap::Message &aMessage);
|
||||
void ForwardUdpProxyToEnroller(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
static Error ReadSteeringDataTlv(const Message &aMessage, SteeringData &aSteeringData);
|
||||
#endif
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
|
||||
void LogUri(Action aAction, const char *aUriString, const char *aTxt);
|
||||
|
||||
@@ -331,6 +358,9 @@ private:
|
||||
template <Uri kUri> void Log(Action, const char *) {}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
OwnedPtr<Admitter::Enroller> mEnroller;
|
||||
#endif
|
||||
LinkedList<ForwardContext> mForwardContexts;
|
||||
TimerMilliContext mTimer;
|
||||
UptimeMsec mAllocationTime;
|
||||
@@ -372,6 +402,11 @@ private:
|
||||
// Callback from `Dnssd`
|
||||
void HandleDnssdPlatformStateChange(void) { RegisterService(); }
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
// Callback from `Admitter`
|
||||
void HandlePrimeAdmitterStateChanged(void) { RegisterService(); }
|
||||
#endif
|
||||
|
||||
const char *GetServiceName(void);
|
||||
bool IsServiceNameEmpty(void) const { return mServiceName[0] == kNullChar; }
|
||||
void ConstrcutServiceName(const char *aBaseName, Dns::Name::LabelBuffer &aNameBuffer);
|
||||
@@ -382,6 +417,10 @@ private:
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
|
||||
static const char kServiceType[];
|
||||
static const char kDefaultBaseServiceName[];
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
static const char kAdmitterSubType[];
|
||||
static const char *const kServiceSubTypes[];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool mEnabled;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,459 @@
|
||||
/*
|
||||
* 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
|
||||
* This file includes definitions for the Border Agent Admitter.
|
||||
*/
|
||||
|
||||
#ifndef OT_CORE_MESHCOP_BORDER_AGENT_ADMITTER_HPP_
|
||||
#define OT_CORE_MESHCOP_BORDER_AGENT_ADMITTER_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
|
||||
#if !OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
#error "Border Admitter requires OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE"
|
||||
#endif
|
||||
|
||||
#include <openthread/border_agent_admitter.h>
|
||||
|
||||
#include "common/error.hpp"
|
||||
#include "common/heap_allocatable.hpp"
|
||||
#include "common/linked_list.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "common/non_copyable.hpp"
|
||||
#include "common/notifier.hpp"
|
||||
#include "common/owning_list.hpp"
|
||||
#include "common/tasklet.hpp"
|
||||
#include "common/time.hpp"
|
||||
#include "common/timer.hpp"
|
||||
#include "common/uptime.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
#include "meshcop/meshcop_tlvs.hpp"
|
||||
#include "net/ip6_address.hpp"
|
||||
#include "net/netif.hpp"
|
||||
#include "net/udp6.hpp"
|
||||
#include "thread/network_data_publisher.hpp"
|
||||
#include "thread/tmf.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace MeshCoP {
|
||||
namespace BorderAgent {
|
||||
|
||||
class Manager;
|
||||
|
||||
/**
|
||||
* Implements a Border Agent Admitter.
|
||||
*/
|
||||
class Admitter : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
friend class Manager;
|
||||
friend class ot::Notifier;
|
||||
friend class NetworkData::Publisher;
|
||||
|
||||
struct Joiner;
|
||||
|
||||
public:
|
||||
typedef otBorderAdmitterEnrollerInfo EnrollerInfo; ///< Information about an enroller.
|
||||
typedef otBorderAdmitterJoinerInfo JoinerInfo; ///< Information about a joiner accepted by an enroller.
|
||||
|
||||
/**
|
||||
* Represents an iterator for enrollers and joiners accepted by an enroller.
|
||||
*/
|
||||
class Iterator : public otBorderAdmitterIterator
|
||||
{
|
||||
friend class Admitter;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Initializes the `Iterator`.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
*/
|
||||
void Init(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* Retrieves the next enroller information.
|
||||
*
|
||||
* @param[out] aEnrollerInfo A `EnrollerInfo` to populate.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the next session. @p aEnrollerInfo is updated.
|
||||
* @retval kErrorNotFound No more entries are available. The end of the list has been reached.
|
||||
*/
|
||||
Error GetNextEnrollerInfo(EnrollerInfo &aEnrollerInfo);
|
||||
|
||||
/**
|
||||
* Retrieves the information about next accepted joiner by the latest retrieved enroller during iteration.
|
||||
*
|
||||
* @param[out] aJoinerInfo A `JoinerInfo` to populate.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the next session. @p aJoinerInfo is updated.
|
||||
* @retval kErrorNotFound No more entries are available. The end of the list has been reached.
|
||||
*/
|
||||
Error GetNextJoinerInfo(JoinerInfo &aJoinerInfo);
|
||||
|
||||
private:
|
||||
void SetSession(SecureSession *aSession) { mPtr1 = aSession; }
|
||||
SecureSession *GetSession(void) const { return static_cast<SecureSession *>(mPtr1); }
|
||||
void SetJoiner(Joiner *aJoiner) { mPtr2 = aJoiner; }
|
||||
Joiner *GetJoiner(void) const { return static_cast<Joiner *>(mPtr2); }
|
||||
UptimeMsec GetInitUptime(void) const { return mData1; }
|
||||
void SetInitUptime(UptimeMsec aUptime) { mData1 = aUptime; }
|
||||
void SetInitTime(TimeMilli aNow) { mData2 = aNow.GetValue(); }
|
||||
TimeMilli GetInitTime(void) const { return TimeMilli(mData2); }
|
||||
|
||||
static void SkipToNextEnrollerSession(SecureSession *&aSession);
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the `Admitter`.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
*/
|
||||
explicit Admitter(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* Enables/Disables the Admitter functionality.
|
||||
*
|
||||
* @param[in] aEnable TRUE to enable, FALSE to disable.
|
||||
*/
|
||||
void SetEnabled(bool aEnable);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the Admitter functionality is enabled.
|
||||
*
|
||||
* @retval TRUE The Admitter functionality is enabled.
|
||||
* @retval FALSE The Admitter functionality is disabled.
|
||||
*/
|
||||
bool IsEnabled(void) const { return mEnabled; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the Admitter is selected and as the prime Admitter within the Thread mesh.
|
||||
*
|
||||
* @retval TRUE The Admitter is the prime Admitter.
|
||||
* @retval FALSE The Admitter is not the prime Admitter.
|
||||
*/
|
||||
bool IsPrimeAdmitter(void) const { return mArbitrator.IsPrimeAdmitter(); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the Admitter is currently acting as the native Commissioner within the Thread mesh.
|
||||
*
|
||||
* @retval TRUE The Admitter is currently native Commissioner.
|
||||
* @retval FALSE The Admitter is not a native Commissioner.
|
||||
*/
|
||||
bool IsActiveCommissioner(void) const { return mCommissionerPetitioner.IsActiveCommissioner(); }
|
||||
|
||||
/**
|
||||
* Indicates whether the Admitter's petition to become the native commissioner within mesh was rejected.
|
||||
*
|
||||
* A rejection typically occurs if there is already another active commissioner in the Thread network.
|
||||
*
|
||||
* @retval TRUE The petition was rejected.
|
||||
* @retval FALSE The petition was not rejected.
|
||||
*/
|
||||
bool IsPetitionRejected(void) const { return mCommissionerPetitioner.IsPetitionRejected(); }
|
||||
|
||||
/**
|
||||
* Gets the Joiner UDP port.
|
||||
*
|
||||
* Zero value indicates the Joiner UDP port is not specified/fixed by the Admitter (Joiner Routers can pick).
|
||||
*
|
||||
* @returns The joiner UDP port number.
|
||||
*/
|
||||
uint16_t GetJoinerUdpPort(void) const { return mCommissionerPetitioner.GetJoinerUdpPort(); }
|
||||
|
||||
/**
|
||||
* Sets the joiner UDP port.
|
||||
*
|
||||
* Zero value indicates the Joiner UDP port is not specified/fixed by the Admitter (Joiner Routers can pick).
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
* @param[in] aUdpPort The UDP port number.
|
||||
*/
|
||||
void SetJoinerUdpPort(uint16_t aUdpPort) { mCommissionerPetitioner.SetJoinerUdpPort(aUdpPort); }
|
||||
|
||||
/**
|
||||
* Gets the commissioner session ID.
|
||||
*
|
||||
* @returns The commissioner session ID when `IsActiveCommissioner()`, zero otherwise.
|
||||
*/
|
||||
uint16_t GetCommissionerSessionId(void) const { return mCommissionerPetitioner.GetSessionId(); }
|
||||
|
||||
private:
|
||||
//-----------------------------------------------------------------------------------------------------------------
|
||||
// Constants and enumerations
|
||||
|
||||
static constexpr bool kEnabledByDefault = OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLED_BY_DEFAULT;
|
||||
static constexpr uint16_t kDefaultJoinerUdpPort = OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_DEFAULT_JOINER_UDP_PORT;
|
||||
|
||||
static constexpr uint32_t kEnrollerKeepAliveTimeout = 50 * Time::kOneSecondInMsec;
|
||||
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStateUnavailable = 0, // Cannot act as Admitter (e.g. disabled/stopped, or there is another Admitter).
|
||||
kStateReady = 1, // Admitter is ready to accept Enroller registrations but not yet active.
|
||||
kStateActive = 2, // Admitter is fully active (it is the native mesh commissioner).
|
||||
kStateConflictError = 3, // Admitter could not become active (e.g., another commissioner is active).
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------
|
||||
// Nested Types
|
||||
|
||||
struct Joiner : public InstanceLocator, LinkedListEntry<Joiner>, Heap::Allocatable<Joiner>
|
||||
{
|
||||
// Track information about a Joiner which is accepted by
|
||||
// an Enroller.
|
||||
|
||||
static constexpr uint32_t kTimeout = 7 * Time::kOneMinuteInMsec;
|
||||
|
||||
Joiner(Instance &aInstance, const Ip6::InterfaceIdentifier &aIid);
|
||||
|
||||
void UpdateExpirationTime(void);
|
||||
bool Matches(const Ip6::InterfaceIdentifier &aIid) const;
|
||||
bool Matches(const ExpirationChecker &aChecker) const;
|
||||
|
||||
Joiner *mNext;
|
||||
Ip6::InterfaceIdentifier mIid;
|
||||
UptimeMsec mAcceptUptime;
|
||||
TimeMilli mExpirationTime;
|
||||
};
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
struct Enroller : Heap::Allocatable<Enroller>
|
||||
{
|
||||
// Tracks information for a registered enroller. This is
|
||||
// included in `CoapDtlsSession` as the member variable
|
||||
// `mEnroller` of type `OwnedPtr<Enroller>`. If the
|
||||
// session is not for an enroller, the `OwnedPtr` will
|
||||
// be null.
|
||||
|
||||
bool ShouldForwardJoinerRelay(void) const { return (mMode & EnrollerModeTlv::kForwardJoinerRelayRx); }
|
||||
bool ShouldForwardUdpProxy(void) const { return (mMode & EnrollerModeTlv::kForwardUdpProxyRx); }
|
||||
|
||||
EnrollerIdTlv::StringType mId;
|
||||
SteeringData mSteeringData;
|
||||
OwningList<Joiner> mJoiners;
|
||||
UptimeMsec mRegisterUptime;
|
||||
uint8_t mMode;
|
||||
};
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
class EnrollerIterator : private NonCopyable
|
||||
{
|
||||
// Iterates over Border Agent sessions and returns only the
|
||||
// ones acting as Enroller.
|
||||
|
||||
public:
|
||||
explicit EnrollerIterator(Instance &aInstance);
|
||||
|
||||
bool IsDone(void) const { return (mSession == nullptr); }
|
||||
void Advance(void);
|
||||
Enroller *GetEnroller(void) const;
|
||||
uint16_t GetSessionIndex(void) const;
|
||||
|
||||
template <typename Type> Type *GetSessionAs(void) const { return static_cast<Type *>(mSession); }
|
||||
|
||||
private:
|
||||
void FindNextEnroller(void) { Iterator::SkipToNextEnrollerSession(mSession); }
|
||||
|
||||
SecureSession *mSession;
|
||||
};
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
void HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent) { mArbitrator.HandlePublisherEvent(aEvent); }
|
||||
void HandleArbitratorTimer(void) { mArbitrator.HandleTimer(); }
|
||||
|
||||
class Arbitrator : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
// Coordinates between Border Agents within mesh to decide which
|
||||
// one can take the prime Admitter role.
|
||||
|
||||
public:
|
||||
explicit Arbitrator(Instance &aInstance);
|
||||
|
||||
void Start(void);
|
||||
void Stop(void);
|
||||
bool IsPrimeAdmitter(void) const { return mState == kPrime; }
|
||||
|
||||
void HandlePublisherEvent(NetworkData::Publisher::Event aEvent);
|
||||
void HandleTimer(void);
|
||||
|
||||
private:
|
||||
static constexpr uint32_t kDelayToBecomePrime = 18 * Time::kOneSecondInMsec;
|
||||
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStopped, // Stopped.
|
||||
kClaiming, // Actively trying to claim the prime role (publishing netdata service).
|
||||
kCandidate, // Is a candidate (netdata service is added - delaying before becoming prime).
|
||||
kPrime, // Is the prime admitter.
|
||||
};
|
||||
|
||||
void SetState(State aState);
|
||||
|
||||
static const char *StateToString(State aState);
|
||||
|
||||
using DelayTimer = TimerMilliIn<Admitter, &Admitter::HandleArbitratorTimer>;
|
||||
|
||||
State mState;
|
||||
DelayTimer mTimer;
|
||||
};
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
void HandleCommissionerPetitionerRetryTimer(void) { mCommissionerPetitioner.HandleRetryTimer(); }
|
||||
void HandleCommissionerPetitionerKeepAliveTimer(void) { mCommissionerPetitioner.HandleKeepAliveTimer(); }
|
||||
|
||||
class CommissionerPetitioner : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
// Manages becoming the native commissioner within mesh.
|
||||
|
||||
public:
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStopped, // Stopped.
|
||||
kToPetition, // To send petition to leader for becoming commissioner.
|
||||
kPetitioning, // Petition request sent, waiting for response from leader.
|
||||
kAcceptedToSyncData, // Petition accepted - need to sync commissioner data with leader.
|
||||
kAcceptedSyncingData, // Petition accepted - commissioner data sync in progress, waiting for response.
|
||||
kAcceptedDataSynced, // Petition accepted - commissioner data sync done.
|
||||
kRejected, // Petition rejected (another commissioner is active).
|
||||
};
|
||||
|
||||
explicit CommissionerPetitioner(Instance &aInstance);
|
||||
|
||||
void Start(void);
|
||||
void Stop(void);
|
||||
State GetState(void) const { return mState; }
|
||||
bool IsActiveCommissioner(void) const;
|
||||
bool IsPetitionRejected(void) const { return (mState == kRejected); }
|
||||
uint16_t GetJoinerUdpPort(void) const { return mJoinerUdpPort; }
|
||||
void SetJoinerUdpPort(uint16_t aUdpPort);
|
||||
uint16_t GetSessionId(void) const { return mSessionId; }
|
||||
const Ip6::Address &GetAloc(void) const { return mAloc.GetAddress(); }
|
||||
|
||||
void HandleEnrollerChange(void);
|
||||
void HandleNetDataChange(void);
|
||||
void HandleRetryTimer(void);
|
||||
void HandleKeepAliveTimer(void);
|
||||
|
||||
private:
|
||||
// All intervals are in msec
|
||||
static constexpr uint32_t kPetitionRetryDelay = Time::kOneSecondInMsec;
|
||||
static constexpr uint16_t kPetitionRetryJitter = 100;
|
||||
static constexpr uint32_t kKeepAliveTxInterval = 25 * Time::kOneSecondInMsec; // Half of timeout used by leader
|
||||
static constexpr uint16_t kKeepAliveTxJitter = 500;
|
||||
static constexpr uint32_t kKeepAliveRetryDelay = Time::kOneSecondInMsec;
|
||||
static constexpr uint16_t kKeepAliveRetryJitter = 100;
|
||||
static constexpr uint32_t kDataSyncRetryDelay = Time::kOneSecondInMsec;
|
||||
static constexpr uint16_t kDataSyncRetryJitter = 100;
|
||||
|
||||
void SetState(State aState);
|
||||
void SendPetitionIfNoOtherCommissioner(void);
|
||||
void SchedulePetitionRetry(void);
|
||||
Error ProcessPetitionResponse(const Coap::Msg *aMsg, Error aResult);
|
||||
void AddAlocAndUdpReceiver(void);
|
||||
void RemoveAlocAndUdpReceiver(void);
|
||||
void ScheduleNextKeepAlive(void);
|
||||
void ScheduleKeepAliveRetry(void);
|
||||
Error SendKeepAlive(StateTlv::State aState);
|
||||
void SendDataSet(void);
|
||||
Error ProcessDataSetResponse(const Coap::Msg *aMsg, Error aResult);
|
||||
void ScheduleDataSyncRetry(void);
|
||||
void ScheduleImmediateDataSync(void);
|
||||
Error SendToLeader(OwnedPtr<Coap::Message> aMessage, Coap::ResponseHandler aHandler);
|
||||
bool HandleUdpReceive(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
DeclareTmfResponseHandlerIn(CommissionerPetitioner, HandlePetitionResponse);
|
||||
DeclareTmfResponseHandlerIn(CommissionerPetitioner, HandleKeepAliveResponse);
|
||||
DeclareTmfResponseHandlerIn(CommissionerPetitioner, HandleDataSetResponse);
|
||||
|
||||
static bool HandleUdpReceive(void *aContext, const otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
static const char *StateToString(State aState);
|
||||
|
||||
using RetryTimer = TimerMilliIn<Admitter, &Admitter::HandleCommissionerPetitionerRetryTimer>;
|
||||
using KeepAliveTimer = TimerMilliIn<Admitter, &Admitter::HandleCommissionerPetitionerKeepAliveTimer>;
|
||||
|
||||
State mState;
|
||||
SteeringData mSteeringData;
|
||||
uint16_t mJoinerUdpPort;
|
||||
uint16_t mSessionId;
|
||||
RetryTimer mRetryTimer;
|
||||
KeepAliveTimer mKeepAliveTimer;
|
||||
Ip6::Udp::Receiver mUdpReceiver;
|
||||
Ip6::Netif::UnicastAddress mAloc;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------
|
||||
// Methods
|
||||
|
||||
State DetermineState(void) const;
|
||||
void EvaluateOperation(void);
|
||||
void PostReportStateTask(void);
|
||||
void HandleReportStateTask(void);
|
||||
void DetermineSteeringData(SteeringData &aSteeringData) const;
|
||||
void ForwardJoinerRelayToEnrollers(const Coap::Msg &aMsg);
|
||||
void ForwardUdpProxyToEnrollers(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void HandleJoinerTimer(void);
|
||||
void HandleEnrollerChange(void);
|
||||
void HandleNotifierEvents(Events aEvents);
|
||||
|
||||
static const char *EnrollerUriToString(Uri aUri);
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------
|
||||
// Variables and Constants
|
||||
|
||||
using JoinerTimer = TimerMilliIn<Admitter, &Admitter::HandleJoinerTimer>;
|
||||
using ReportStateTask = TaskletIn<Admitter, &Admitter::HandleReportStateTask>;
|
||||
|
||||
static const uint8_t kEnrollerValidSteeringDataLengths[];
|
||||
|
||||
bool mEnabled;
|
||||
bool mHasAnyEnroller;
|
||||
Arbitrator mArbitrator;
|
||||
CommissionerPetitioner mCommissionerPetitioner;
|
||||
JoinerTimer mJoinerTimer;
|
||||
ReportStateTask mReportStateTask;
|
||||
State mLastSyncedState;
|
||||
};
|
||||
|
||||
} // namespace BorderAgent
|
||||
} // namespace MeshCoP
|
||||
|
||||
DefineCoreType(otBorderAdmitterIterator, MeshCoP::BorderAgent::Admitter::Iterator);
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
|
||||
#endif // OT_CORE_MESHCOP_BORDER_AGENT_ADMITTER_HPP_
|
||||
@@ -262,6 +262,13 @@ uint32_t TxtData::StateBitmap::Determine(Instance &aInstance)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
if (aInstance.Get<Admitter>().IsEnabled())
|
||||
{
|
||||
bitmap |= kFlagAdmitterSupported;
|
||||
}
|
||||
#endif
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@@ -431,9 +438,10 @@ void TxtData::StateBitmap::Parse(uint32_t aBitmap, Info &aInfo)
|
||||
aInfo.mThreadRole = static_cast<Role>((aBitmap & kMaskRole) >> kOffsetRole);
|
||||
aInfo.mMultiAilState =
|
||||
static_cast<otBorderAgentMultiAilState>((aBitmap & kMaskMultiAilState) >> kOffsetMultiAilState);
|
||||
aInfo.mBbrIsActive = aBitmap & kFlagBbrIsActive;
|
||||
aInfo.mBbrIsPrimary = aBitmap & kFlagBbrIsPrimary;
|
||||
aInfo.mEpskcSupported = aBitmap & kFlagEpskcSupported;
|
||||
aInfo.mBbrIsActive = aBitmap & kFlagBbrIsActive;
|
||||
aInfo.mBbrIsPrimary = aBitmap & kFlagBbrIsPrimary;
|
||||
aInfo.mEpskcSupported = aBitmap & kFlagEpskcSupported;
|
||||
aInfo.mAdmitterSupported = aBitmap & kFlagAdmitterSupported;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
|
||||
|
||||
@@ -265,23 +265,25 @@ private:
|
||||
|
||||
struct StateBitmap
|
||||
{
|
||||
static constexpr uint8_t kOffsetConnMode = 0;
|
||||
static constexpr uint8_t kOffsetIfState = 3;
|
||||
static constexpr uint8_t kOffsetAvailability = 5;
|
||||
static constexpr uint8_t kOffsetBbrIsActive = 7;
|
||||
static constexpr uint8_t kOffsetBbrIsPrimary = 8;
|
||||
static constexpr uint8_t kOffsetRole = 9;
|
||||
static constexpr uint8_t kOffsetEpskcSupported = 11;
|
||||
static constexpr uint8_t kOffsetMultiAilState = 12;
|
||||
static constexpr uint8_t kOffsetConnMode = 0;
|
||||
static constexpr uint8_t kOffsetIfState = 3;
|
||||
static constexpr uint8_t kOffsetAvailability = 5;
|
||||
static constexpr uint8_t kOffsetBbrIsActive = 7;
|
||||
static constexpr uint8_t kOffsetBbrIsPrimary = 8;
|
||||
static constexpr uint8_t kOffsetRole = 9;
|
||||
static constexpr uint8_t kOffsetEpskcSupported = 11;
|
||||
static constexpr uint8_t kOffsetMultiAilState = 12;
|
||||
static constexpr uint8_t kOffsetAdmitterSupported = 14;
|
||||
|
||||
static constexpr uint32_t kMaskConnMode = 7 << kOffsetConnMode;
|
||||
static constexpr uint32_t kMaskIfState = 3 << kOffsetIfState;
|
||||
static constexpr uint32_t kMaskAvailability = 3 << kOffsetAvailability;
|
||||
static constexpr uint32_t kFlagBbrIsActive = 1 << kOffsetBbrIsActive;
|
||||
static constexpr uint32_t kFlagBbrIsPrimary = 1 << kOffsetBbrIsPrimary;
|
||||
static constexpr uint32_t kMaskRole = 3 << kOffsetRole;
|
||||
static constexpr uint32_t kFlagEpskcSupported = 1 << kOffsetEpskcSupported;
|
||||
static constexpr uint32_t kMaskMultiAilState = 3 << kOffsetMultiAilState;
|
||||
static constexpr uint32_t kMaskConnMode = 7 << kOffsetConnMode;
|
||||
static constexpr uint32_t kMaskIfState = 3 << kOffsetIfState;
|
||||
static constexpr uint32_t kMaskAvailability = 3 << kOffsetAvailability;
|
||||
static constexpr uint32_t kFlagBbrIsActive = 1 << kOffsetBbrIsActive;
|
||||
static constexpr uint32_t kFlagBbrIsPrimary = 1 << kOffsetBbrIsPrimary;
|
||||
static constexpr uint32_t kMaskRole = 3 << kOffsetRole;
|
||||
static constexpr uint32_t kFlagEpskcSupported = 1 << kOffsetEpskcSupported;
|
||||
static constexpr uint32_t kMaskMultiAilState = 3 << kOffsetMultiAilState;
|
||||
static constexpr uint32_t kFlagAdmitterSupported = 1 << kOffsetAdmitterSupported;
|
||||
|
||||
static_assert(kConnModeDisabled == 0, "kConnModeDisabled is incorrect");
|
||||
static_assert(kConnModePskc == 1, "kConnModePskc is incorrect");
|
||||
|
||||
@@ -113,6 +113,9 @@ public:
|
||||
kEnergyList = OT_MESHCOP_TLV_ENERGY_LIST, ///< Energy List TLV
|
||||
kThreadDomainName = OT_MESHCOP_TLV_THREAD_DOMAIN_NAME, ///< Thread Domain Name TLV
|
||||
kWakeupChannel = OT_MESHCOP_TLV_WAKEUP_CHANNEL, ///< Wakeup Channel TLV
|
||||
kAdmitterState = OT_MESHCOP_TLV_ADMITTER_STATE, ///< Admitter State TLV
|
||||
kEnrollerId = OT_MESHCOP_TLV_ENROLLER_ID, ///< Enroller ID TLV
|
||||
kEnrollerMode = OT_MESHCOP_TLV_ENROLLER_MODE, ///< Enroller Mode TLV
|
||||
kDiscoveryRequest = OT_MESHCOP_TLV_DISCOVERYREQUEST, ///< Discovery Request TLV
|
||||
kDiscoveryResponse = OT_MESHCOP_TLV_DISCOVERYRESPONSE, ///< Discovery Response TLV
|
||||
kJoinerAdvertisement = OT_MESHCOP_TLV_JOINERADVERTISEMENT, ///< Joiner Advertisement TLV
|
||||
@@ -124,6 +127,7 @@ public:
|
||||
static constexpr uint8_t kMaxProvisioningUrlLength = OT_PROVISIONING_URL_MAX_SIZE;
|
||||
|
||||
static constexpr uint8_t kMaxCommissionerIdLength = 64; ///< Max length of Commissioner ID TLV.
|
||||
static constexpr uint8_t kMaxEnrollerIdLength = 64; ///< Max length of Enroller ID TLV.
|
||||
static constexpr uint8_t kMaxVendorNameLength = 32; ///< Max length of Vendor Name TLV.
|
||||
static constexpr uint8_t kMaxVendorModelLength = 32; ///< Max length of Vendor Model TLV.
|
||||
static constexpr uint8_t kMaxVendorSwVersionLength = 16; ///< Max length of Vendor SW Version TLV.
|
||||
@@ -1154,6 +1158,30 @@ private:
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE
|
||||
|
||||
/**
|
||||
* Defines Enroller ID TLV constants and types.
|
||||
*/
|
||||
typedef StringTlvInfo<Tlv::kEnrollerId, Tlv::kMaxEnrollerIdLength> EnrollerIdTlv;
|
||||
|
||||
/**
|
||||
* Defines Admitter State TLV constants and types.
|
||||
*
|
||||
*State values are defined in `BorderAgent::Admitter`
|
||||
*/
|
||||
typedef UintTlvInfo<Tlv::kAdmitterState, uint8_t> AdmitterStateTlv;
|
||||
|
||||
/**
|
||||
* Implements Enroller Mode TLV generation and parsing.
|
||||
*/
|
||||
class EnrollerModeTlv : public UintTlvInfo<Tlv::kEnrollerMode, uint8_t>
|
||||
{
|
||||
public:
|
||||
EnrollerModeTlv(void) = delete;
|
||||
|
||||
static constexpr uint8_t kForwardJoinerRelayRx = 1 << 7; ///< Forward RelayRx (from Joiners) to Enroller.
|
||||
static constexpr uint8_t kForwardUdpProxyRx = 1 << 6; ///< Forward UDP ProxyRx to Enroller.
|
||||
};
|
||||
|
||||
} // namespace MeshCoP
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -150,6 +150,11 @@ exit:
|
||||
return contains;
|
||||
}
|
||||
|
||||
bool SteeringData::operator==(const SteeringData &aOther) const
|
||||
{
|
||||
return (GetLength() == aOther.GetLength()) && (memcmp(GetData(), aOther.GetData(), GetLength()) == 0);
|
||||
}
|
||||
|
||||
void SteeringData::CalculateHashBitIndexes(const Mac::ExtAddress &aJoinerId, HashBitIndexes &aIndexes)
|
||||
{
|
||||
aIndexes.mIndex[0] = CrcCalculator<uint16_t>(kCrc16CcittPolynomial).Feed(aJoinerId);
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/equatable.hpp"
|
||||
#include "common/error.hpp"
|
||||
#include "common/string.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
@@ -53,7 +54,7 @@ class JoinerDiscerner;
|
||||
/**
|
||||
* Represents Steering Data (bloom filter).
|
||||
*/
|
||||
class SteeringData : public otSteeringData
|
||||
class SteeringData : public otSteeringData, public Unequatable<SteeringData>
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kMinLength = OT_STEERING_DATA_MIN_LENGTH; ///< Minimum Steering Data length (in bytes).
|
||||
@@ -216,6 +217,16 @@ public:
|
||||
*/
|
||||
bool Contains(const HashBitIndexes &aIndexes) const;
|
||||
|
||||
/**
|
||||
* Overloads operator `==` to compare two Steering Data instances.
|
||||
*
|
||||
* @param[in] aOther The other `SteeringData` to compare with.
|
||||
*
|
||||
* @retval TRUE If the two Steering Data instances are equal.
|
||||
* @retval FALSE If the two Steering Data instances are not equal.
|
||||
*/
|
||||
bool operator==(const SteeringData &aOther) const;
|
||||
|
||||
/**
|
||||
* Converts the Steering Data to a human-readable string representation.
|
||||
*
|
||||
|
||||
@@ -148,6 +148,13 @@ public:
|
||||
*/
|
||||
Address &GetAddress(void) { return AsCoreType(&mAddress); }
|
||||
|
||||
/**
|
||||
* Sets the unicast address.
|
||||
*
|
||||
* @param[in] aAddress The unicast address.
|
||||
*/
|
||||
void SetAddress(const Address &aAddress) { mAddress = aAddress; }
|
||||
|
||||
/**
|
||||
* Returns the address's prefix length (in bits).
|
||||
*
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "config/announce_sender.h"
|
||||
#include "config/backbone_router.h"
|
||||
#include "config/border_agent.h"
|
||||
#include "config/border_agent_admitter.h"
|
||||
#include "config/border_router.h"
|
||||
#include "config/border_routing.h"
|
||||
#include "config/channel_manager.h"
|
||||
|
||||
@@ -49,6 +49,9 @@ Publisher::Publisher(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
, mDnsSrpServiceEntry(aInstance)
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
, mBorderAdmitterEntry(aInstance)
|
||||
#endif
|
||||
#endif
|
||||
, mTimer(aInstance)
|
||||
{
|
||||
@@ -220,6 +223,9 @@ void Publisher::HandleNotifierEvents(Events aEvents)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
mDnsSrpServiceEntry.HandleNotifierEvents(aEvents);
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
mBorderAdmitterEntry.HandleNotifierEvents(aEvents);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
@@ -234,6 +240,9 @@ void Publisher::HandleTimer(void)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
mDnsSrpServiceEntry.HandleTimer();
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
mBorderAdmitterEntry.HandleTimer();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
@@ -386,6 +395,12 @@ void Publisher::Entry::Add(void)
|
||||
{
|
||||
static_cast<DnsSrpServiceEntry *>(this)->Add();
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
if (Get<Publisher>().IsBorderAdmitterEntry(*this))
|
||||
{
|
||||
static_cast<BorderAdmitterEntry *>(this)->Add();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
@@ -403,6 +418,12 @@ void Publisher::Entry::Remove(State aNextState)
|
||||
{
|
||||
static_cast<DnsSrpServiceEntry *>(this)->Remove(aNextState);
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
if (Get<Publisher>().IsBorderAdmitterEntry(*this))
|
||||
{
|
||||
static_cast<BorderAdmitterEntry *>(this)->Remove(aNextState);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
@@ -423,6 +444,13 @@ Publisher::Entry::InfoString Publisher::Entry::ToString(bool aIncludeState) cons
|
||||
string.Append("DNS/SRP service");
|
||||
ExitNow();
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
if (Get<Publisher>().IsBorderAdmitterEntry(*this))
|
||||
{
|
||||
string.Append("Border Admitter service");
|
||||
ExitNow();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
@@ -766,6 +794,107 @@ Publisher::DnsSrpServiceEntry::Info::Info(Type aType,
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Publisher::BorderAddmitterEntry
|
||||
|
||||
Publisher::BorderAdmitterEntry::BorderAdmitterEntry(Instance &aInstance) { Init(aInstance); }
|
||||
|
||||
void Publisher::BorderAdmitterEntry::Publish(void)
|
||||
{
|
||||
VerifyOrExit(GetState() == kNoEntry);
|
||||
LogInfo("Publishing Border Admitter service");
|
||||
SetState(kToAdd);
|
||||
Process();
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Publisher::BorderAdmitterEntry::Unpublish(void)
|
||||
{
|
||||
VerifyOrExit(GetState() != kNoEntry);
|
||||
LogInfo("Unpublishing Border Admitter service");
|
||||
Remove(/* aNextState */ kNoEntry);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Publisher::BorderAdmitterEntry::HandleNotifierEvents(Events aEvents)
|
||||
{
|
||||
if (aEvents.ContainsAny(kEventThreadNetdataChanged | kEventThreadRoleChanged))
|
||||
{
|
||||
Process();
|
||||
}
|
||||
}
|
||||
|
||||
void Publisher::BorderAdmitterEntry::Add(void)
|
||||
{
|
||||
SuccessOrExit(Get<Service::Manager>().AddBorderAdmitterService());
|
||||
Get<Notifier>().HandleServerDataUpdated();
|
||||
SetState(kAdded);
|
||||
Notify(kEventEntryAdded);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Publisher::BorderAdmitterEntry::Remove(State aNextState)
|
||||
{
|
||||
VerifyOrExit((GetState() == kAdded) || (GetState() == kRemoving));
|
||||
|
||||
SuccessOrExit(Get<Service::Manager>().RemoveBorderAdmitterService());
|
||||
Get<Notifier>().HandleServerDataUpdated();
|
||||
Notify(kEventEntryRemoved);
|
||||
|
||||
exit:
|
||||
SetState(aNextState);
|
||||
}
|
||||
|
||||
void Publisher::BorderAdmitterEntry::Notify(Event aEvent) const
|
||||
{
|
||||
Get<MeshCoP::BorderAgent::Admitter>().HandleNetDataPublisherEvent(aEvent);
|
||||
}
|
||||
|
||||
void Publisher::BorderAdmitterEntry::Process(void)
|
||||
{
|
||||
// This method checks the entries currently present in Network Data
|
||||
// based on which it then decides whether or not take action
|
||||
// (add/remove or keep monitoring).
|
||||
|
||||
uint8_t numEntries = 0;
|
||||
uint8_t numPreferredEntries = 0;
|
||||
|
||||
VerifyOrExit(Get<Mle::Mle>().IsAttached());
|
||||
VerifyOrExit(GetState() != kNoEntry);
|
||||
|
||||
CountEntries(numEntries, numPreferredEntries);
|
||||
UpdateState(numEntries, numPreferredEntries, kDesiredNum);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Publisher::BorderAdmitterEntry::CountEntries(uint8_t &aNumEntries, uint8_t &aNumPreferredEntries) const
|
||||
{
|
||||
Service::Iterator iterator(GetInstance());
|
||||
uint16_t rloc16;
|
||||
|
||||
while (iterator.GetNextBorderAdmitterInfo(rloc16) == kErrorNone)
|
||||
{
|
||||
aNumEntries++;
|
||||
|
||||
if (IsPreferred(rloc16))
|
||||
{
|
||||
aNumPreferredEntries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
|
||||
@@ -188,6 +188,26 @@ public:
|
||||
*/
|
||||
void UnpublishDnsSrpService(void) { mDnsSrpServiceEntry.Unpublish(); }
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
/**
|
||||
* Requests Border Admitter service entry to be published in the Thread Network Data.
|
||||
*/
|
||||
void PublishBorderAdmitterService(void) { mBorderAdmitterEntry.Publish(); }
|
||||
|
||||
/**
|
||||
* Unpublishes any previously added Border Admitter service entry from the Network Data.
|
||||
*/
|
||||
void UnpublishBorderAdmitterService(void) { mBorderAdmitterEntry.Unpublish(); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the Border Admitter service entry has been added in the Thread Network Data.
|
||||
*
|
||||
* @retval TRUE The published service entry is added to the Thread Network Data.
|
||||
* @retval FALSE The entry is not added to Thread Network Data or there is no entry to publish.
|
||||
*/
|
||||
bool IsBorderAdmitterServicePublished(void) { return mBorderAdmitterEntry.IsAdded(); }
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
@@ -440,6 +460,30 @@ private:
|
||||
Info mInfo;
|
||||
Callback<DnsSrpServiceCallback> mCallback;
|
||||
};
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
class BorderAdmitterEntry : public Entry, private NonCopyable
|
||||
{
|
||||
friend class Entry;
|
||||
|
||||
public:
|
||||
explicit BorderAdmitterEntry(Instance &aInstance);
|
||||
void Publish(void);
|
||||
void Unpublish(void);
|
||||
void HandleTimer(void) { Entry::HandleTimer(); }
|
||||
void HandleNotifierEvents(Events aEvents);
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kDesiredNum = 1;
|
||||
|
||||
void Add(void);
|
||||
void Remove(State aNextState);
|
||||
void Notify(Event aEvent) const;
|
||||
void Process(void);
|
||||
void CountEntries(uint8_t &aNumEntries, uint8_t &aNumPreferredEntries) const;
|
||||
};
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
@@ -499,6 +543,9 @@ private:
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
bool IsADnsSrpServiceEntry(const Entry &aEntry) const { return (&aEntry == &mDnsSrpServiceEntry); }
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
bool IsBorderAdmitterEntry(const Entry &aEntry) const { return (&aEntry == &mBorderAdmitterEntry); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
@@ -517,6 +564,9 @@ private:
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
DnsSrpServiceEntry mDnsSrpServiceEntry;
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
BorderAdmitterEntry mBorderAdmitterEntry;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
|
||||
@@ -183,6 +183,40 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
|
||||
Error Iterator::GetNextBorderAdmitterInfo(uint16_t &aRloc16)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint8_t serviceNumber = Manager::kBorderAdmitterServiceNumber;
|
||||
do
|
||||
{
|
||||
ServiceData serviceData;
|
||||
|
||||
// Process the next Server sub-TLV within the current Service TLV.
|
||||
|
||||
if (AdvanceToNextServer() == kErrorNone)
|
||||
{
|
||||
aRloc16 = mServerSubTlv->GetServer16();
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
// Find the next matching Service TLV.
|
||||
|
||||
serviceData.InitFrom(serviceNumber);
|
||||
mServiceTlv = mNetworkData.FindNextThreadService(mServiceTlv, serviceData, NetworkData::kServicePrefixMatch);
|
||||
mServerSubTlv = nullptr;
|
||||
|
||||
} while (mServiceTlv != nullptr);
|
||||
|
||||
error = kErrorNotFound;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
|
||||
Error Iterator::AdvanceToNextServer(void)
|
||||
{
|
||||
Error error = kErrorNotFound;
|
||||
|
||||
@@ -144,6 +144,21 @@ public:
|
||||
*/
|
||||
Error GetNextDnsSrpUnicastInfo(DnsSrpUnicastType aType, DnsSrpUnicastInfo &aInfo);
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
/**
|
||||
* Gets the next Border Admitter service info from the Thread Network Data Border Admitter servcie entries.
|
||||
*
|
||||
* To start from the first service entry, ensure the iterator is reset (e.g., by creating a new `Iterator`
|
||||
* instance, or by calling `Reset()`).
|
||||
*
|
||||
* @param[out] aRloc16 On success, returns the RLOC16 or device which added Border Admitter service entry.
|
||||
*
|
||||
* @retval kErrorNone Successfully got the next info. @p aRloc16 is updated.
|
||||
* @retval kErrorNotFound No more matching entries in the Network Data.
|
||||
*/
|
||||
Error GetNextBorderAdmitterInfo(uint16_t &aRloc16);
|
||||
#endif
|
||||
|
||||
private:
|
||||
Error AdvanceToNextServer(void);
|
||||
|
||||
@@ -277,6 +292,24 @@ public:
|
||||
Error RemoveBackboneRouterService(void) { return RemoveService(kBackboneRouterServiceNumber); }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE
|
||||
/**
|
||||
* Adds a Border Admitter Service entry to the local Thread Network Data.
|
||||
*
|
||||
* @retval kErrorNone Successfully added the Service entry.
|
||||
* @retval kErrorNoBufs Insufficient space to add the Service entry.
|
||||
*/
|
||||
Error AddBorderAdmitterService(void) { return AddService(kBorderAdmitterServiceNumber); }
|
||||
|
||||
/**
|
||||
* Removes the Border Admitter Service entry from the local Thread Network Data.
|
||||
*
|
||||
* @retval kErrorNone Successfully removed the Service entry.
|
||||
* @retval kErrorNotFound Could not find the Service entry.
|
||||
*/
|
||||
Error RemoveBorderAdmitterService(void) { return RemoveService(kBorderAdmitterServiceNumber); }
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
||||
@@ -322,6 +355,7 @@ private:
|
||||
static constexpr uint8_t kBackboneRouterServiceNumber = 0x01;
|
||||
static constexpr uint8_t kDnsSrpAnycastServiceNumber = 0x5c;
|
||||
static constexpr uint8_t kDnsSrpUnicastServiceNumber = 0x5d;
|
||||
static constexpr uint8_t kBorderAdmitterServiceNumber = 0xad;
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
@@ -504,6 +538,8 @@ private:
|
||||
return AddService(&aServiceData, aServiceData.GetLength(), &aServerData, sizeof(ServerDataType));
|
||||
}
|
||||
|
||||
Error AddService(uint8_t aServiceNumber) { return AddService(&aServiceNumber, sizeof(uint8_t), nullptr, 0); }
|
||||
|
||||
Error AddService(const void *aServiceData,
|
||||
uint8_t aServiceDataLength,
|
||||
const void *aServerData,
|
||||
|
||||
+12
-3
@@ -284,7 +284,7 @@ SecureAgent::SecureAgent(Instance &aInstance)
|
||||
{
|
||||
SetAcceptCallback(&HandleDtlsAccept, this);
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
|
||||
#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE) || OPENTHREAD_PLATFORM_NEXUS
|
||||
SetResourceHandler(&HandleResource);
|
||||
#endif
|
||||
}
|
||||
@@ -301,7 +301,7 @@ Coap::SecureSession *SecureAgent::HandleDtlsAccept(void)
|
||||
return IsSessionInUse() ? nullptr : static_cast<Coap::SecureSession *>(this);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
|
||||
#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE) || OPENTHREAD_PLATFORM_NEXUS
|
||||
|
||||
bool SecureAgent::HandleResource(CoapBase &aCoapBase, const char *aUriPath, Msg &aMsg)
|
||||
{
|
||||
@@ -313,16 +313,25 @@ bool SecureAgent::HandleResource(const char *aUriPath, Msg &aMsg)
|
||||
bool didHandle = false;
|
||||
Uri uri = UriFromPath(aUriPath);
|
||||
|
||||
#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE)
|
||||
if (uri == kUriJoinerFinalize)
|
||||
{
|
||||
Get<MeshCoP::Commissioner>().HandleTmf<kUriJoinerFinalize>(aMsg);
|
||||
didHandle = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_PLATFORM_NEXUS
|
||||
if (mResourceHandler.IsSet())
|
||||
{
|
||||
didHandle = mResourceHandler.Invoke(uri, aMsg);
|
||||
}
|
||||
#endif
|
||||
|
||||
return didHandle;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
|
||||
#endif // (OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE) || OPENTHREAD_PLATFORM_NEXUS
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
|
||||
|
||||
+28
-1
@@ -39,6 +39,7 @@
|
||||
#include "coap/coap.hpp"
|
||||
#include "coap/coap_secure.hpp"
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/callback.hpp"
|
||||
#include "common/locator.hpp"
|
||||
|
||||
namespace ot {
|
||||
@@ -229,14 +230,40 @@ public:
|
||||
*/
|
||||
explicit SecureAgent(Instance &aInstance);
|
||||
|
||||
#if OPENTHREAD_PLATFORM_NEXUS
|
||||
/**
|
||||
* Represents a resource handler callback function.
|
||||
*
|
||||
* @param[in] aContext An arbitrary context (provided when callback is registered).
|
||||
* @param[in] aUriPath The URI.
|
||||
* @param[in] aMsg The received message.
|
||||
*
|
||||
* @retval TRUE Indicates that the URI was known and the message was processed by the handler.
|
||||
* @retval FALSE Indicates that the URI was not known and the message was not processed by the handler.
|
||||
*/
|
||||
typedef bool (*ResourceHandler)(void *aContext, Uri aUri, Msg &aMsg);
|
||||
|
||||
/**
|
||||
* Registers a resource handler callback.
|
||||
*
|
||||
* @param[in] aHandler The handler function pointer.
|
||||
* @param[in] aContext An arbitrary context (passed to the @p aHandler when it is invoked).
|
||||
*/
|
||||
void RegisterResourceHandler(ResourceHandler aHandler, void *aContext) { mResourceHandler.Set(aHandler, aContext); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
static MeshCoP::SecureSession *HandleDtlsAccept(void *aContext, const Ip6::MessageInfo &aMessageInfo);
|
||||
Coap::SecureSession *HandleDtlsAccept(void);
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
|
||||
#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE) || OPENTHREAD_PLATFORM_NEXUS
|
||||
static bool HandleResource(CoapBase &aCoapBase, const char *aUriPath, Msg &aMsg);
|
||||
bool HandleResource(const char *aUriPath, Msg &aMsg);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_PLATFORM_NEXUS
|
||||
Callback<ResourceHandler> mResourceHandler;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -78,6 +78,11 @@ static constexpr Entry kEntries[] = {
|
||||
{"c/jf"}, // kUriJoinerFinalize
|
||||
{"c/la"}, // kUriLeaderKeepAlive
|
||||
{"c/lp"}, // kUriLeaderPetition
|
||||
{"c/nj"}, // kUriEnrollerJoinerAccept
|
||||
{"c/nk"}, // kUriEnrollerKeepAlive
|
||||
{"c/nl"}, // kUriEnrollerJoinerRelease
|
||||
{"c/nr"}, // kUriEnrollerRegister
|
||||
{"c/ns"}, // kUriEnrollerReportState
|
||||
{"c/pc"}, // kUriPanIdConflict
|
||||
{"c/pg"}, // kUriPendingGet
|
||||
{"c/pq"}, // kUriPanIdQuery
|
||||
@@ -126,6 +131,11 @@ static_assert(AreConstStringsEqual(kEntries[kUriJoinerEntrust].mPath, "c/je"), "
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriJoinerFinalize].mPath, "c/jf"), "kEntries is invalid");
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriLeaderKeepAlive].mPath, "c/la"), "kEntries is invalid");
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriLeaderPetition].mPath, "c/lp"), "kEntries is invalid");
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriEnrollerJoinerAccept].mPath, "c/nj"), "kEntries is invalid");
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriEnrollerKeepAlive].mPath, "c/nk"), "kEntries is invalid");
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriEnrollerJoinerRelease].mPath, "c/nl"), "kEntries is invalid");
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriEnrollerRegister].mPath, "c/nr"), "kEntries is invalid");
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriEnrollerReportState].mPath, "c/ns"), "kEntries is invalid");
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriPanIdConflict].mPath, "c/pc"), "kEntries is invalid");
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriPendingGet].mPath, "c/pg"), "kEntries is invalid");
|
||||
static_assert(AreConstStringsEqual(kEntries[kUriPanIdQuery].mPath, "c/pq"), "kEntries is invalid");
|
||||
@@ -191,6 +201,11 @@ template <> const char *UriToString<kUriJoinerEntrust>(void) { return "JoinerEnt
|
||||
template <> const char *UriToString<kUriJoinerFinalize>(void) { return "JoinerFinalize"; }
|
||||
template <> const char *UriToString<kUriLeaderKeepAlive>(void) { return "LeaderKeepAlive"; }
|
||||
template <> const char *UriToString<kUriLeaderPetition>(void) { return "LeaderPetition"; }
|
||||
template <> const char *UriToString<kUriEnrollerJoinerAccept>(void) { return "EnrollerJoinerAccept"; }
|
||||
template <> const char *UriToString<kUriEnrollerKeepAlive>(void) { return "EnrollerKeepAlive"; }
|
||||
template <> const char *UriToString<kUriEnrollerJoinerRelease>(void) { return "EnrollerJoinerRelease"; }
|
||||
template <> const char *UriToString<kUriEnrollerRegister>(void) { return "EnrollerRegister"; }
|
||||
template <> const char *UriToString<kUriEnrollerReportState>(void) { return "EnrollerReportState"; }
|
||||
template <> const char *UriToString<kUriPanIdConflict>(void) { return "PanIdConflict"; }
|
||||
template <> const char *UriToString<kUriPendingGet>(void) { return "PendingGet"; }
|
||||
template <> const char *UriToString<kUriPanIdQuery>(void) { return "PanIdQuery"; }
|
||||
|
||||
@@ -70,6 +70,11 @@ enum Uri : uint8_t
|
||||
kUriJoinerFinalize, ///< Joiner Finalize ("c/jf")
|
||||
kUriLeaderKeepAlive, ///< Leader Keep Alive ("c/la")
|
||||
kUriLeaderPetition, ///< Leader Petition ("c/lp")
|
||||
kUriEnrollerJoinerAccept, ///< Enroller Joiner Accept ("c/nj")
|
||||
kUriEnrollerKeepAlive, ///< Enroller KeepAlive ("c/nk")
|
||||
kUriEnrollerJoinerRelease, ///< Enroller Joiner Release ("c/nl")
|
||||
kUriEnrollerRegister, ///< Enroller Register ("c/nr")
|
||||
kUriEnrollerReportState, ///< Report Admitter State (to enroller) ("c/ns")
|
||||
kUriPanIdConflict, ///< PAN ID Conflict ("c/pc")
|
||||
kUriPendingGet, ///< MGMT_PENDING_GET ("c/pg")
|
||||
kUriPanIdQuery, ///< PAN ID Query ("c/pq")
|
||||
@@ -144,6 +149,11 @@ template <> const char *UriToString<kUriJoinerEntrust>(void);
|
||||
template <> const char *UriToString<kUriJoinerFinalize>(void);
|
||||
template <> const char *UriToString<kUriLeaderKeepAlive>(void);
|
||||
template <> const char *UriToString<kUriLeaderPetition>(void);
|
||||
template <> const char *UriToString<kUriEnrollerJoinerAccept>(void);
|
||||
template <> const char *UriToString<kUriEnrollerKeepAlive>(void);
|
||||
template <> const char *UriToString<kUriEnrollerJoinerRelease>(void);
|
||||
template <> const char *UriToString<kUriEnrollerRegister>(void);
|
||||
template <> const char *UriToString<kUriEnrollerReportState>(void);
|
||||
template <> const char *UriToString<kUriPanIdConflict>(void);
|
||||
template <> const char *UriToString<kUriPendingGet>(void);
|
||||
template <> const char *UriToString<kUriPanIdQuery>(void);
|
||||
|
||||
@@ -132,6 +132,7 @@ ot_nexus_test(5_1_13 "cert;nexus")
|
||||
ot_nexus_test(5_2_1 "cert;nexus")
|
||||
|
||||
# Misc tests
|
||||
ot_nexus_test(border_admitter "core;nexus")
|
||||
ot_nexus_test(border_agent "core;nexus")
|
||||
ot_nexus_test(border_agent_tracker "core;nexus")
|
||||
ot_nexus_test(discover_scan "core;nexus")
|
||||
|
||||
@@ -44,8 +44,11 @@
|
||||
#define OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BLE_TCAT_ENABLE 0
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLED_BY_DEFAULT 0
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_COMMISSIONER_EVICTION_API_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,6 +40,7 @@ using ActiveDatasetManager = MeshCoP::ActiveDatasetManager;
|
||||
using Manager = MeshCoP::BorderAgent::Manager;
|
||||
using BaTxtData = MeshCoP::BorderAgent::TxtData;
|
||||
using EphemeralKeyManager = MeshCoP::BorderAgent::EphemeralKeyManager;
|
||||
using Admitter = MeshCoP::BorderAgent::Admitter;
|
||||
using EpskcEvent = HistoryTracker::EpskcEvent;
|
||||
using Iterator = HistoryTracker::Iterator;
|
||||
using NetworkIdentity = MeshCoP::NetworkIdentity;
|
||||
@@ -1308,6 +1309,7 @@ void ValidateMeshCoPTxtData(TxtData &aTxtData, Node &aNode)
|
||||
static constexpr uint32_t kThreadRoleRouter = 2 << 9;
|
||||
static constexpr uint32_t kThreadRoleLeader = 3 << 9;
|
||||
static constexpr uint32_t kFlagEpskcSupported = 1 << 11;
|
||||
static constexpr uint32_t kFlagAdmitterSupported = 1 << 14;
|
||||
|
||||
MeshCoP::BorderAgent::Id id;
|
||||
BaTxtData::Info info;
|
||||
@@ -1434,6 +1436,17 @@ void ValidateMeshCoPTxtData(TxtData &aTxtData, Node &aNode)
|
||||
VerifyOrQuit(!(stateBitmap & kFlagEpskcSupported));
|
||||
VerifyOrQuit(!info.mStateBitmap.mEpskcSupported);
|
||||
}
|
||||
|
||||
if (aNode.Get<Admitter>().IsEnabled())
|
||||
{
|
||||
VerifyOrQuit(stateBitmap & kFlagAdmitterSupported);
|
||||
VerifyOrQuit(info.mStateBitmap.mAdmitterSupported);
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrQuit(!(stateBitmap & kFlagAdmitterSupported));
|
||||
VerifyOrQuit(!info.mStateBitmap.mAdmitterSupported);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1888,6 +1901,86 @@ void TestBorderAgentServiceRegistration(void)
|
||||
sSrvOutcomes.Clear();
|
||||
sTxtOutcomes.Clear();
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Enable Admitter function");
|
||||
|
||||
node0.Get<Admitter>().SetEnabled(true);
|
||||
VerifyOrQuit(node0.Get<Admitter>().IsEnabled());
|
||||
|
||||
nexus.AdvanceTime(5 * Time::kOneSecondInMsec);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Check the registered service");
|
||||
|
||||
iterator = node0.Get<Dns::Multicast::Core>().AllocateIterator();
|
||||
VerifyOrQuit(iterator != nullptr);
|
||||
|
||||
iterator = node0.Get<Dns::Multicast::Core>().AllocateIterator();
|
||||
VerifyOrQuit(iterator != nullptr);
|
||||
|
||||
SuccessOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState));
|
||||
Log(" HostName: %s", service.mHostName);
|
||||
Log(" ServiceInstance: %s", service.mServiceInstance);
|
||||
Log(" ServiceType: %s", service.mServiceType);
|
||||
Log(" Port: %u", service.mPort);
|
||||
Log(" TTL: %lu", ToUlong(service.mTtl));
|
||||
|
||||
VerifyOrQuit(StringMatch(service.mServiceType, "_meshcop._udp"));
|
||||
VerifyOrQuit(StringStartsWith(service.mServiceInstance, "OpenThreadAgent"));
|
||||
VerifyOrQuit(StringStartsWith(service.mHostName, "ot"));
|
||||
VerifyOrQuit(service.mSubTypeLabelsLength == 0);
|
||||
VerifyOrQuit(service.mPort == node0.Get<MeshCoP::BorderAgent::Manager>().GetUdpPort());
|
||||
VerifyOrQuit(service.mTtl > 0);
|
||||
VerifyOrQuit(service.mInfraIfIndex == kInfraIfIndex);
|
||||
VerifyOrQuit(entryState == OT_MDNS_ENTRY_STATE_REGISTERED);
|
||||
ValidateRegisteredServiceData(service, node0);
|
||||
|
||||
// Check that there is no more registered mDNS service
|
||||
VerifyOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState) == kErrorNotFound);
|
||||
|
||||
node0.Get<Dns::Multicast::Core>().FreeIterator(*iterator);
|
||||
|
||||
nexus.AdvanceTime(10 * Time::kOneSecondInMsec);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Disable Admitter function");
|
||||
|
||||
node0.Get<Admitter>().SetEnabled(false);
|
||||
VerifyOrQuit(!node0.Get<Admitter>().IsEnabled());
|
||||
|
||||
nexus.AdvanceTime(5 * Time::kOneSecondInMsec);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Check the registered service");
|
||||
|
||||
iterator = node0.Get<Dns::Multicast::Core>().AllocateIterator();
|
||||
VerifyOrQuit(iterator != nullptr);
|
||||
|
||||
iterator = node0.Get<Dns::Multicast::Core>().AllocateIterator();
|
||||
VerifyOrQuit(iterator != nullptr);
|
||||
|
||||
SuccessOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState));
|
||||
Log(" HostName: %s", service.mHostName);
|
||||
Log(" ServiceInstance: %s", service.mServiceInstance);
|
||||
Log(" ServiceType: %s", service.mServiceType);
|
||||
Log(" Port: %u", service.mPort);
|
||||
Log(" TTL: %lu", ToUlong(service.mTtl));
|
||||
|
||||
VerifyOrQuit(StringMatch(service.mServiceType, "_meshcop._udp"));
|
||||
VerifyOrQuit(StringStartsWith(service.mServiceInstance, "OpenThreadAgent"));
|
||||
VerifyOrQuit(StringStartsWith(service.mHostName, "ot"));
|
||||
VerifyOrQuit(service.mSubTypeLabelsLength == 0);
|
||||
VerifyOrQuit(service.mPort == node0.Get<MeshCoP::BorderAgent::Manager>().GetUdpPort());
|
||||
VerifyOrQuit(service.mTtl > 0);
|
||||
VerifyOrQuit(service.mInfraIfIndex == kInfraIfIndex);
|
||||
VerifyOrQuit(entryState == OT_MDNS_ENTRY_STATE_REGISTERED);
|
||||
ValidateRegisteredServiceData(service, node0);
|
||||
|
||||
// Check that there is no more registered mDNS service
|
||||
VerifyOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState) == kErrorNotFound);
|
||||
|
||||
node0.Get<Dns::Multicast::Core>().FreeIterator(*iterator);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Disable Border Agent and validate that registered service is removed");
|
||||
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_COMMISSIONER_EVICTION_API_ENABLE 1
|
||||
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_ADMITTER_ENABLE 1
|
||||
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE 1
|
||||
|
||||
#define OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE 1
|
||||
|
||||
Reference in New Issue
Block a user