Skip to content

Commit

Permalink
[settings] define new Settings key for Border Router ID (openthread#8971
Browse files Browse the repository at this point in the history
)

This commit adds new Border Agent functionality that generates and
saves 16 bytes ID in settings.  The ID can be published in the MeshCoP
mDNS service and used by the client to identify a Border Router
device.

A new `otBorderAgentGetId()` API is defined and the ID is generated
the first time this API is called.
  • Loading branch information
wgtdkp authored May 5, 2023
1 parent 96ea730 commit eaa2779
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 4 deletions.
1 change: 1 addition & 0 deletions etc/cmake/options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,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_BORDER_AGENT OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE "border agent")
ot_option(OT_BORDER_AGENT_ID OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE "create and save border agent ID")
ot_option(OT_BORDER_ROUTER OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE "border router")
ot_option(OT_BORDER_ROUTING OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE "border routing")
ot_option(OT_BORDER_ROUTING_COUNTERS OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE "border routing counters")
Expand Down
3 changes: 3 additions & 0 deletions etc/gn/openthread.gni
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ if (openthread_enable_core_config_args) {
# Enable border agent support
openthread_config_border_agent_enable = false

# Enable border agent ID
openthread_config_border_agent_id_enable = false

# Enable border router support
openthread_config_border_router_enable = false

Expand Down
24 changes: 24 additions & 0 deletions include/openthread/border_agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ extern "C" {
*
*/

/**
* The length of Border Agent/Router ID in bytes.
*
*/
#define OT_BORDER_AGENT_ID_LENGTH (16)

/**
* This enumeration defines the Border Agent state.
*
Expand Down Expand Up @@ -82,6 +88,24 @@ otBorderAgentState otBorderAgentGetState(otInstance *aInstance);
*/
uint16_t otBorderAgentGetUdpPort(otInstance *aInstance);

/**
* Gets the randomly generated Border Agent ID.
*
* The ID is saved in persistent storage and survives reboots. The typical use case of the ID is to
* be published in the MeshCoP mDNS service as the `id` TXT value for the client to identify this
* Border Router/Agent device.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[out] aId A pointer to buffer to receive the ID.
* @param[inout] aLength Specifies the length of `aId` when used as input and receives the length
* actual ID data copied to `aId` when used as output.
*
* @retval OT_ERROR_INVALID_ARGS If value of `aLength` if smaller than `OT_BORDER_AGENT_ID_LENGTH`.
* @retval OT_ERROR_NONE If successfully retrieved the Border Agent ID.
*
*/
otError otBorderAgentGetId(otInstance *aInstance, uint8_t *aId, uint16_t *aLength);

/**
* @}
*
Expand Down
2 changes: 1 addition & 1 deletion include/openthread/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (317)
#define OPENTHREAD_API_VERSION (318)

/**
* @addtogroup api-instance
Expand Down
1 change: 1 addition & 0 deletions include/openthread/platform/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ enum
OT_SETTINGS_KEY_SRP_SERVER_INFO = 0x000d, ///< The SRP server info (UDP port).
OT_SETTINGS_KEY_BR_ULA_PREFIX = 0x000f, ///< BR ULA prefix.
OT_SETTINGS_KEY_BR_ON_LINK_PREFIXES = 0x0010, ///< BR local on-link prefixes.
OT_SETTINGS_KEY_BORDER_AGENT_ID = 0x0011, ///< Unique Border Agent/Router ID.

// Deprecated and reserved key values:
//
Expand Down
7 changes: 7 additions & 0 deletions src/core/api/border_agent_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@

using namespace ot;

#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
otError otBorderAgentGetId(otInstance *aInstance, uint8_t *aId, uint16_t *aLength)
{
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent>().GetId(aId, *aLength);
}
#endif

otBorderAgentState otBorderAgentGetState(otInstance *aInstance)
{
return MapEnum(AsCoreType(aInstance).Get<MeshCoP::BorderAgent>().GetState());
Expand Down
34 changes: 32 additions & 2 deletions src/core/common/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,28 @@ void SettingsBase::SrpServerInfo::Log(Action aAction) const
}
#endif

#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
Error SettingsBase::BorderAgentId::SetId(const uint8_t *aId, uint16_t aLength)
{
Error error = kErrorNone;

VerifyOrExit(aLength == sizeof(mId), error = kErrorInvalidArgs);
memcpy(mId, aId, aLength);

exit:
return error;
}

void SettingsBase::BorderAgentId::Log(Action aAction) const
{
char buffer[sizeof(BorderAgentId) * 2 + 1];
StringWriter sw(buffer, sizeof(buffer));

sw.AppendHexBytes(GetId(), sizeof(BorderAgentId));
LogInfo("%s BorderAgentId {id:%s}", ActionToString(aAction), buffer);
}
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE

#endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)

#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
Expand Down Expand Up @@ -157,7 +179,8 @@ const char *SettingsBase::KeyToString(Key aKey)
"SrpServerInfo", // (13) kKeySrpServerInfo
"", // (14) Removed (previously NAT64 prefix)
"BrUlaPrefix", // (15) kKeyBrUlaPrefix
"BrOnLinkPrefixes" // (16) kKeyBrOnLinkPrefixes
"BrOnLinkPrefixes", // (16) kKeyBrOnLinkPrefixes
"BorderAgentId" // (17) kKeyBorderAgentId
};

static_assert(1 == kKeyActiveDataset, "kKeyActiveDataset value is incorrect");
Expand All @@ -172,8 +195,9 @@ const char *SettingsBase::KeyToString(Key aKey)
static_assert(13 == kKeySrpServerInfo, "kKeySrpServerInfo value is incorrect");
static_assert(15 == kKeyBrUlaPrefix, "kKeyBrUlaPrefix value is incorrect");
static_assert(16 == kKeyBrOnLinkPrefixes, "kKeyBrOnLinkPrefixes is incorrect");
static_assert(17 == kKeyBorderAgentId, "kKeyBorderAgentId is incorrect");

static_assert(kLastKey == kKeyBrOnLinkPrefixes, "kLastKey is not valid");
static_assert(kLastKey == kKeyBorderAgentId, "kLastKey is not valid");

OT_ASSERT(aKey <= kLastKey);

Expand Down Expand Up @@ -518,6 +542,12 @@ void Settings::Log(Action aAction, Error aError, Key aKey, const void *aValue)
break;
#endif

#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
case kKeyBorderAgentId:
reinterpret_cast<const BorderAgentId *>(aValue)->Log(aAction);
break;
#endif

default:
// For any other keys, we do not want to include the value
// in the log, so even if it is given we set `aValue` to
Expand Down
56 changes: 55 additions & 1 deletion src/core/common/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "common/settings_driver.hpp"
#include "crypto/ecdsa.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/border_agent.hpp"
#include "meshcop/dataset.hpp"
#include "net/ip6_address.hpp"
#include "thread/version.hpp"
Expand Down Expand Up @@ -120,9 +121,10 @@ class SettingsBase : public InstanceLocator
kKeySrpServerInfo = OT_SETTINGS_KEY_SRP_SERVER_INFO,
kKeyBrUlaPrefix = OT_SETTINGS_KEY_BR_ULA_PREFIX,
kKeyBrOnLinkPrefixes = OT_SETTINGS_KEY_BR_ON_LINK_PREFIXES,
kKeyBorderAgentId = OT_SETTINGS_KEY_BORDER_AGENT_ID,
};

static constexpr Key kLastKey = kKeyBrOnLinkPrefixes; ///< The last (numerically) enumerator value in `Key`.
static constexpr Key kLastKey = kKeyBorderAgentId; ///< The last (numerically) enumerator value in `Key`.

static_assert(static_cast<uint16_t>(kLastKey) < static_cast<uint16_t>(OT_SETTINGS_KEY_VENDOR_RESERVED_MIN),
"Core settings keys overlap with vendor reserved keys");
Expand Down Expand Up @@ -765,6 +767,58 @@ class SettingsBase : public InstanceLocator
} OT_TOOL_PACKED_END;
#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE

#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
/**
* This structure represents the Border Agent ID.
*
*/
OT_TOOL_PACKED_BEGIN
class BorderAgentId : private Clearable<BorderAgentId>
{
friend class Settings;
friend class Clearable<BorderAgentId>;

public:
static constexpr Key kKey = kKeyBorderAgentId; ///< The associated key.

/**
* This method initializes the `BorderAgentId` object.
*
*/
void Init(void) { Clear(); }

/**
* This method returns the Border Agent ID.
*
* @returns The Border Agent ID.
*
*/
const uint8_t *GetId(void) const { return mId; }

/**
* This method returns the Border Agent ID.
*
* @returns The Border Agent ID.
*
*/
uint8_t *GetId(void) { return mId; }

/**
* This method sets the Border Agent ID.
*
* @retval kErrorInvalidArgs If `aLength` doesn't equal to `OT_BORDER_AGENT_ID_LENGTH`.
* @retval kErrorNone If success.
*
*/
Error SetId(const uint8_t *aId, uint16_t aLength);

private:
void Log(Action aAction) const;

uint8_t mId[MeshCoP::BorderAgent::kIdLength];
} OT_TOOL_PACKED_END;
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE

protected:
explicit SettingsBase(Instance &aInstance)
: InstanceLocator(aInstance)
Expand Down
10 changes: 10 additions & 0 deletions src/core/config/border_agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,14 @@
#define OPENTHREAD_CONFIG_BORDER_AGENT_UDP_PORT 0
#endif

/**
* @def OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
*
* Define ro 1 to enable Border Agent ID support.
*
*/
#ifndef OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
#define OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE 0
#endif

#endif // CONFIG_BORDER_AGENT_H_
31 changes: 31 additions & 0 deletions src/core/meshcop/border_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,41 @@ BorderAgent::BorderAgent(Instance &aInstance)
, mTimer(aInstance)
, mState(kStateStopped)
, mUdpProxyPort(0)
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
, mIdInitialized(false)
#endif
{
mCommissionerAloc.InitAsThreadOriginRealmLocalScope();
}

#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
Error BorderAgent::GetId(uint8_t *aId, uint16_t &aLength)
{
Error error = kErrorNone;

static_assert(sizeof(mId) == kIdLength, "Invalid Border Agent ID size");

VerifyOrExit(aLength >= sizeof(mId), error = kErrorInvalidArgs);
VerifyOrExit(!mIdInitialized, error = kErrorNone);

if (Get<Settings>().Read(mId) != kErrorNone)
{
Random::NonCrypto::FillBuffer(mId.GetId(), sizeof(mId));
SuccessOrExit(error = Get<Settings>().Save(mId));
}

mIdInitialized = true;

exit:
if (error == kErrorNone)
{
memcpy(aId, mId.GetId(), sizeof(mId));
aLength = static_cast<uint16_t>(sizeof(mId));
}
return error;
}
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE

void BorderAgent::HandleNotifierEvents(Events aEvents)
{
VerifyOrExit(aEvents.ContainsAny(kEventThreadRoleChanged | kEventCommissionerStateChanged));
Expand Down
27 changes: 27 additions & 0 deletions src/core/meshcop/border_agent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ class BorderAgent : public InstanceLocator, private NonCopyable
friend class Tmf::SecureAgent;

public:
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
static constexpr uint8_t kIdLength = OT_BORDER_AGENT_ID_LENGTH;
#endif

/**
* This enumeration defines the Border Agent state.
*
Expand All @@ -78,6 +82,25 @@ class BorderAgent : public InstanceLocator, private NonCopyable
*/
explicit BorderAgent(Instance &aInstance);

#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
/**
* Gets the randomly generated Border Agent ID.
*
* The ID is saved in persistent storage and survives reboots. The typical use case of the ID is to
* be published in the MeshCoP mDNS service as the `id` TXT value for the client to identify this
* Border Router/Agent device.
*
* @param[out] aId A pointer to buffer to receive the ID.
* @param[inout] aLength Specifies the length of `aId` when used as input and receives the length
* actual ID data copied to `aId` when used as output.
*
* @retval OT_ERROR_INVALID_ARGS If value of `aLength` if smaller than `OT_BORDER_AGENT_ID_LENGTH`.
* @retval OT_ERROR_NONE If successfully retrieved the Border Agent ID.
*
*/
Error GetId(uint8_t *aId, uint16_t &aLength);
#endif

/**
* This method gets the UDP port of this service.
*
Expand Down Expand Up @@ -178,6 +201,10 @@ class BorderAgent : public InstanceLocator, private NonCopyable
TimeoutTimer mTimer;
State mState;
uint16_t mUdpProxyPort;
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
Settings::BorderAgentId mId;
bool mIdInitialized;
#endif
};

DeclareTmfHandler(BorderAgent, kUriRelayRx);
Expand Down

0 comments on commit eaa2779

Please sign in to comment.