[border-agent] introduce Border Agent TXT Data Parser (#12009)

This commit introduces a new feature to parse the MeshCoP service TXT
data from a Border Agent.

The new API `otBorderAgentTxtDataParse()` allows parsing the raw TXT
data into a structured `otBorderAgentTxtDataInfo` object. This can be
used by applications to inspect the capabilities and status of a
discovered Border Agent.

Config `OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE` controls
this new feature.

The existing test for the Border Agent is updated to validate the new
parser and its output.
This commit is contained in:
Abtin Keshavarzian
2025-10-22 09:40:18 +08:00
committed by GitHub
parent ecd29ced66
commit ad1cfb749e
14 changed files with 729 additions and 146 deletions
+1
View File
@@ -310,6 +310,7 @@ openthread_core_files = [
"api/ble_secure_api.cpp",
"api/border_agent_api.cpp",
"api/border_agent_tracker_api.cpp",
"api/border_agent_txt_data_api.cpp",
"api/border_router_api.cpp",
"api/border_routing_api.cpp",
"api/channel_manager_api.cpp",
+1
View File
@@ -36,6 +36,7 @@ set(COMMON_SOURCES
api/ble_secure_api.cpp
api/border_agent_api.cpp
api/border_agent_tracker_api.cpp
api/border_agent_txt_data_api.cpp
api/border_router_api.cpp
api/border_routing_api.cpp
api/channel_manager_api.cpp
@@ -0,0 +1,51 @@
/*
* 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 TXT data parsing APIs.
*/
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
#include <openthread/border_agent_txt_data.h>
#include "instance/instance.hpp"
using namespace ot;
otError otBorderAgentTxtDataParse(const uint8_t *aTxtData, uint16_t aTxtDataLength, otBorderAgentTxtDataInfo *aInfo)
{
AssertPointerIsNotNull(aTxtData);
return AsCoreType(aInfo).ParseFrom(aTxtData, aTxtDataLength);
}
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
+9
View File
@@ -134,6 +134,15 @@
#define OPENTHREAD_CONFIG_BORDER_AGENT_TRACKER_ENABLE 0
#endif
/**
* @def OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
*
* Define to 1 to enable the Border Agent TXT Data Parser feature.
*/
#ifndef OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
#define OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE 0
#endif
/**
* @}
*/
+184 -8
View File
@@ -33,13 +33,14 @@
#include "border_agent_txt_data.hpp"
#include "common/string.hpp"
#include "instance/instance.hpp"
namespace ot {
namespace MeshCoP {
namespace BorderAgent {
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE || OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
const char TxtData::kRecordVersion[] = "1";
@@ -56,12 +57,18 @@ const char TxtData::Key::kBbrSeqNum[] = "sq";
const char TxtData::Key::kBbrPort[] = "bb";
const char TxtData::Key::kOmrPrefix[] = "omr";
const char TxtData::Key::kExtAddress[] = "xa";
#if OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
const char TxtData::Key::kVendorName[] = "vn";
const char TxtData::Key::kModelName[] = "mn";
#endif
TxtData::TxtData(Instance &aInstance)
: InstanceLocator(aInstance)
{
}
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
Error TxtData::Prepare(uint8_t *aBuffer, uint16_t aBufferSize, uint16_t &aLength)
{
Error error = kErrorNone;
@@ -157,25 +164,25 @@ uint32_t TxtData::StateBitmap::Determine(Instance &aInstance)
{
uint32_t bitmap = 0;
bitmap |= (aInstance.Get<Manager>().IsRunning() ? kConnectionModePskc : kConnectionModeDisabled);
bitmap |= kAvailabilityHigh;
bitmap |= ((aInstance.Get<Manager>().IsRunning() ? kConnModePskc : kConnModeDisabled) << kOffsetConnMode);
bitmap |= (kAvailabilityHigh << kOffsetAvailability);
switch (aInstance.Get<Mle::Mle>().GetRole())
{
case Mle::DeviceRole::kRoleDisabled:
bitmap |= (kThreadIfStatusNotInitialized | kThreadRoleDisabledOrDetached);
bitmap |= (kThreadIfNotInit << kOffsetIfState) | (kRoleDisabledDetached << kOffsetRole);
break;
case Mle::DeviceRole::kRoleDetached:
bitmap |= (kThreadIfStatusInitialized | kThreadRoleDisabledOrDetached);
bitmap |= (kThreadIfInit << kOffsetIfState) | (kRoleDisabledDetached << kOffsetRole);
break;
case Mle::DeviceRole::kRoleChild:
bitmap |= (kThreadIfStatusActive | kThreadRoleChild);
bitmap |= (kThreadIfActive << kOffsetIfState) | (kRoleChild << kOffsetRole);
break;
case Mle::DeviceRole::kRoleRouter:
bitmap |= (kThreadIfStatusActive | kThreadRoleRouter);
bitmap |= (kThreadIfActive << kOffsetIfState) | (kRoleRouter << kOffsetRole);
break;
case Mle::DeviceRole::kRoleLeader:
bitmap |= (kThreadIfStatusActive | kThreadRoleLeader);
bitmap |= (kThreadIfActive << kOffsetIfState) | (kRoleLeader << kOffsetRole);
break;
}
@@ -199,6 +206,175 @@ uint32_t TxtData::StateBitmap::Determine(Instance &aInstance)
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
#if OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
Error TxtData::Info::ParseFrom(const uint8_t *aTxtData, uint16_t aTxtDataLength)
{
Error error;
Dns::TxtEntry entry;
Dns::TxtEntry::Iterator iterator;
Clear();
iterator.Init(aTxtData, aTxtDataLength);
while ((error = iterator.GetNextEntry(entry)) == kErrorNone)
{
ProcessTxtEntry(entry);
}
if (error == kErrorNotFound)
{
error = kErrorNone;
}
return error;
}
void TxtData::Info::ProcessTxtEntry(const Dns::TxtEntry &aEntry)
{
if (aEntry.mKey == nullptr)
{
// If the TXT data happens to have entries with key longer
// than `kMaxIterKeyLength`, `mKey` would be `nullptr` and full
// entry would be placed in `mValue`. We skip over such
// entries.
}
else if (StringMatch(aEntry.mKey, Key::kRecordVersion))
{
ReadStringValue(aEntry, mRecordVersion);
mHasRecordVersion = true;
}
else if (StringMatch(aEntry.mKey, Key::kAgentId))
{
mHasAgentId = ReadValue(aEntry, mAgentId);
}
else if (StringMatch(aEntry.mKey, Key::kThreadVersion))
{
ReadStringValue(aEntry, mThreadVersion);
mHasThreadVersion = true;
}
else if (StringMatch(aEntry.mKey, Key::kStateBitmap))
{
uint32_t bitmap;
if (ReadBigEndianUintValue(aEntry, bitmap))
{
StateBitmap::Parse(bitmap, mStateBitmap);
mHasStateBitmap = true;
}
}
else if (StringMatch(aEntry.mKey, Key::kNetworkName))
{
ReadStringValue(aEntry, mNetworkName.m8);
mHasNetworkName = true;
}
else if (StringMatch(aEntry.mKey, Key::kExtendedPanId))
{
mHasExtendedPanId = ReadValue(aEntry, mExtendedPanId);
}
else if (StringMatch(aEntry.mKey, Key::kActiveTimestamp))
{
Timestamp timestamp;
if (ReadValue(aEntry, timestamp))
{
timestamp.ConvertTo(mActiveTimestamp);
mHasActiveTimestamp = true;
}
}
else if (StringMatch(aEntry.mKey, Key::kPartitionId))
{
mHasPartitionId = ReadBigEndianUintValue(aEntry, mPartitionId);
}
else if (StringMatch(aEntry.mKey, Key::kDomainName))
{
ReadStringValue(aEntry, mDomainName.m8);
mHasDomainName = true;
}
else if (StringMatch(aEntry.mKey, Key::kBbrSeqNum))
{
mHasBbrSeqNum = ReadBigEndianUintValue(aEntry, mBbrSeqNum);
}
else if (StringMatch(aEntry.mKey, Key::kBbrPort))
{
mHasBbrPort = ReadBigEndianUintValue(aEntry, mBbrPort);
}
else if (StringMatch(aEntry.mKey, Key::kOmrPrefix))
{
mHasOmrPrefix = ReadOmrPrefix(aEntry, AsCoreType(&mOmrPrefix));
}
else if (StringMatch(aEntry.mKey, Key::kExtAddress))
{
mHasExtAddress = ReadValue(aEntry, mExtAddress);
}
else if (StringMatch(aEntry.mKey, Key::kVendorName))
{
ReadStringValue(aEntry, mVendorName);
mHasVendorName = true;
}
else if (StringMatch(aEntry.mKey, Key::kModelName))
{
ReadStringValue(aEntry, mModelName);
mHasModelName = true;
}
}
bool TxtData::Info::ReadValue(const Dns::TxtEntry &aEntry, void *aBuffer, uint16_t aSize)
{
bool didRead = false;
VerifyOrExit(aEntry.mValueLength >= aSize);
memcpy(aBuffer, aEntry.mValue, aSize);
didRead = true;
exit:
return didRead;
}
void TxtData::Info::ReadStringValue(const Dns::TxtEntry &aEntry, char *aString, uint16_t aStringSize)
{
uint16_t copyLength = Min<uint16_t>(aStringSize - 1, aEntry.mValueLength);
memcpy(aString, aEntry.mValue, copyLength);
aString[copyLength] = kNullChar;
}
bool TxtData::Info::ReadOmrPrefix(const Dns::TxtEntry &aEntry, Ip6::Prefix &aPrefix)
{
bool didRead = false;
uint8_t length;
VerifyOrExit(aEntry.mValueLength >= sizeof(uint8_t));
length = aEntry.mValue[0];
VerifyOrExit(length <= Ip6::Prefix::kMaxLength);
VerifyOrExit(aEntry.mValueLength >= sizeof(uint8_t) + Ip6::Prefix::SizeForLength(length));
aPrefix.Set(&aEntry.mValue[1], length);
didRead = true;
exit:
return didRead;
}
void TxtData::StateBitmap::Parse(uint32_t aBitmap, Info &aInfo)
{
ClearAllBytes(aInfo);
aInfo.mConnMode = static_cast<ConnMode>((aBitmap & kMaskConnMode) >> kOffsetConnMode);
aInfo.mThreadIfState = static_cast<IfState>((aBitmap & kMaskIfState) >> kOffsetIfState);
aInfo.mAvailability = static_cast<Availability>((aBitmap & kMaskAvailability) >> kOffsetAvailability);
aInfo.mThreadRole = static_cast<Role>((aBitmap & kMaskRole) >> kOffsetRole);
aInfo.mBbrIsActive = aBitmap & kFlagBbrIsActive;
aInfo.mBbrIsPrimary = aBitmap & kFlagBbrIsPrimary;
aInfo.mEpskcSupported = aBitmap & kFlagEpskcSupported;
}
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE || OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
} // namespace BorderAgent
} // namespace MeshCoP
} // namespace ot
+143 -42
View File
@@ -37,20 +37,48 @@
#include "openthread-core-config.h"
#include <openthread/border_agent.h>
#include <openthread/border_agent_txt_data.h>
#include "common/as_core_type.hpp"
#include "common/clearable.hpp"
#include "common/encoding.hpp"
#include "common/error.hpp"
#include "common/locator.hpp"
#include "common/type_traits.hpp"
#include "net/dns_types.hpp"
#include "net/ip6_address.hpp"
namespace ot {
namespace MeshCoP {
namespace BorderAgent {
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE || OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
class TxtData : public InstanceLocator
{
public:
typedef otBorderAgentMeshCoPServiceTxtData ServiceTxtData; ///< Service TXT Data.
typedef otBorderAgentConnMode ConnMode; ///< Connection Mode in a Border Agent State Bitmap.
typedef otBorderAgentThreadIfState IfState; ///< Thread Interface State in a Border Agent State Bitmap.
typedef otBorderAgentAvailability Availability; ///< Availability Status in a Border Agent State Bitmap.
typedef otBorderAgentThreadRole Role; ///< Thread Role in a Border Agent State Bitmap.
static constexpr ConnMode kConnModeDisabled = OT_BORDER_AGENT_CONN_MODE_DISABLED; ///< Not allowed.
static constexpr ConnMode kConnModePskc = OT_BORDER_AGENT_CONN_MODE_PSKC; ///< DTLS with PSKc.
static constexpr ConnMode kConnModePskd = OT_BORDER_AGENT_CONN_MODE_PSKD; ///< DTLS with PSKd.
static constexpr ConnMode kConnModeVendor = OT_BORDER_AGENT_CONN_MODE_VENDOR; ///< Vendor defined.
static constexpr ConnMode kConnModeX509 = OT_BORDER_AGENT_CONN_MODE_X509; ///< DTLS X.509 cert.
static constexpr IfState kThreadIfNotInit = OT_BORDER_AGENT_THREAD_IF_NOT_INITIALIZED; ///< Not init.
static constexpr IfState kThreadIfInit = OT_BORDER_AGENT_THREAD_IF_INITIALIZED; ///< Init but not active.
static constexpr IfState kThreadIfActive = OT_BORDER_AGENT_THREAD_IF_ACTIVE; ///< Init and active.
static constexpr Availability kAvailabilityInfreq = OT_BORDER_AGENT_AVAILABILITY_INFREQUENT; ///< Infrequent.
static constexpr Availability kAvailabilityHigh = OT_BORDER_AGENT_AVAILABILITY_HIGH; ///< High.
static constexpr Role kRoleDisabledDetached = OT_BORDER_AGENT_THREAD_ROLE_DISABLED_OR_DETACHED; ///< Detach.
static constexpr Role kRoleChild = OT_BORDER_AGENT_THREAD_ROLE_CHILD; ///< Child.
static constexpr Role kRoleRouter = OT_BORDER_AGENT_THREAD_ROLE_ROUTER; ///< Router.
static constexpr Role kRoleLeader = OT_BORDER_AGENT_THREAD_ROLE_LEADER; ///< Leader.
/**
* Initializes the `TxtData` object.
@@ -59,6 +87,68 @@ public:
*/
TxtData(Instance &aInstance);
#if OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
/**
* Represents information parsed from a Border Agent TXT Data.
*/
class Info : public otBorderAgentTxtDataInfo, public Clearable<Info>
{
public:
/**
* Parses a Border Agent's MeshCoP service TXT data.
*
* @param[in] aTxtData A pointer to the buffer containing the TXT data.
* @param[in] aTxtDataLength The length of the TXT data in bytes.
*
* @retval kErrorNone Successfully parsed the TXT data.
* @retval kErrorParse Failed to parse the TXT data.
*/
Error ParseFrom(const uint8_t *aTxtData, uint16_t aTxtDataLength);
private:
void ProcessTxtEntry(const Dns::TxtEntry &aEntry);
static bool ReadValue(const Dns::TxtEntry &aEntry, void *aBuffer, uint16_t aSize);
static void ReadStringValue(const Dns::TxtEntry &aEntry, char *aString, uint16_t aStringSize);
static bool ReadOmrPrefix(const Dns::TxtEntry &aEntry, Ip6::Prefix &aPrefix);
template <typename ObjectType> bool ReadValue(const Dns::TxtEntry &aEntry, ObjectType &aObject)
{
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
return ReadValue(aEntry, &aObject, sizeof(aObject));
}
template <uint16_t kStringSize>
static void ReadStringValue(const Dns::TxtEntry &aEntry, char (&aString)[kStringSize])
{
ReadStringValue(aEntry, aString, kStringSize);
}
template <typename UintType>
static bool ReadBigEndianUintValue(const Dns::TxtEntry &aEntry, UintType &aUintValue)
{
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be a 8, 16, 32, or 64 bit uint");
bool didRead = false;
if (aEntry.mValueLength >= sizeof(UintType))
{
aUintValue = BigEndian::Read<UintType>(aEntry.mValue);
didRead = true;
}
return didRead;
}
};
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
typedef otBorderAgentMeshCoPServiceTxtData ServiceTxtData; ///< Service TXT Data.
/**
* Prepares the MeshCoP service TXT data.
*
@@ -81,6 +171,8 @@ public:
*/
Error Prepare(ServiceTxtData &aTxtData);
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
private:
static const char kRecordVersion[];
@@ -99,60 +191,69 @@ private:
static const char kBbrPort[];
static const char kOmrPrefix[];
static const char kExtAddress[];
#if OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
static const char kVendorName[];
static const char kModelName[];
#endif
};
struct StateBitmap
{
static uint32_t Determine(Instance &aInstance);
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;
// --- State Bitmap ConnectionMode ---
static constexpr uint8_t kOffsetConnectionMode = 0;
static constexpr uint32_t kMaskConnectionMode = 7 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModeDisabled = 0 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModePskc = 1 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModePskd = 2 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModeVendor = 3 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModeX509 = 4 << kOffsetConnectionMode;
// --- State Bitmap ThreadIfStatus ---
static constexpr uint8_t kOffsetThreadIfStatus = 3;
static constexpr uint32_t kMaskThreadIfStatus = 3 << kOffsetThreadIfStatus;
static constexpr uint32_t kThreadIfStatusNotInitialized = 0 << kOffsetThreadIfStatus;
static constexpr uint32_t kThreadIfStatusInitialized = 1 << kOffsetThreadIfStatus;
static constexpr uint32_t kThreadIfStatusActive = 2 << kOffsetThreadIfStatus;
// --- State Bitmap Availability ---
static constexpr uint8_t kOffsetAvailability = 5;
static constexpr uint32_t kMaskAvailability = 3 << kOffsetAvailability;
static constexpr uint32_t kAvailabilityInfrequent = 0 << kOffsetAvailability;
static constexpr uint32_t kAvailabilityHigh = 1 << kOffsetAvailability;
// --- State Bitmap BbrIsActive ---
static constexpr uint8_t kOffsetBbrIsActive = 7;
static constexpr uint32_t kFlagBbrIsActive = 1 << kOffsetBbrIsActive;
// --- State Bitmap BbrIsPrimary ---
static constexpr uint8_t kOffsetBbrIsPrimary = 8;
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;
// --- State Bitmap ThreadRole ---
static constexpr uint8_t kOffsetThreadRole = 9;
static constexpr uint32_t kMaskThreadRole = 3 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleDisabledOrDetached = 0 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleChild = 1 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleRouter = 2 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleLeader = 3 << kOffsetThreadRole;
static_assert(kConnModeDisabled == 0, "kConnModeDisabled is incorrect");
static_assert(kConnModePskc == 1, "kConnModePskc is incorrect");
static_assert(kConnModePskd == 2, "kConnModePskd is incorrect");
static_assert(kConnModeVendor == 3, "kConnModeVendor is incorrect");
static_assert(kConnModeX509 == 4, "kConnModeX509 is incorrect");
// --- State Bitmap EpskcSupported ---
static constexpr uint8_t kOffsetEpskcSupported = 11;
static constexpr uint32_t kFlagEpskcSupported = 1 << kOffsetEpskcSupported;
static_assert(kThreadIfNotInit == 0, "kThreadIfNotInit is incorrect");
static_assert(kThreadIfInit == 1, "kThreadIfInit is incorrect");
static_assert(kThreadIfActive == 2, "kThreadIfActive is incorrect");
static_assert(kAvailabilityInfreq == 0, "kAvailabilityInfreq is incorrect");
static_assert(kAvailabilityHigh == 1, "kAvailabilityHigh is incorrect");
static_assert(kRoleDisabledDetached == 0, "kRoleDisabledDetached is incorrect");
static_assert(kRoleChild == 1, "kRoleChild is incorrect");
static_assert(kRoleRouter == 2, "kRoleRouter is incorrect");
static_assert(kRoleLeader == 3, "kRoleLeader is incorrect");
#if OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
typedef otBorderAgentStateBitmap Info;
static void Parse(uint32_t aBitmap, Info &aInfo);
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
static uint32_t Determine(Instance &aInstance);
#endif
};
};
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE || OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
} // namespace BorderAgent
} // namespace MeshCoP
#if OPENTHREAD_CONFIG_BORDER_AGENT_TXT_DATA_PARSER_ENABLE
DefineCoreType(otBorderAgentTxtDataInfo, MeshCoP::BorderAgent::TxtData::Info);
#endif
} // namespace ot
#endif // BORDER_AGENT_TXT_DATA_HPP_