mirror of
https://github.com/espressif/openthread.git
synced 2026-07-29 23:27:46 +00:00
[mle-router] leader to handle "BR request" in an Address Solicit (#7578)
This commit adds support for new Status TLV values and updates the processing of Address Solicit request messages on leader. The new status `kBorderRouterRequest` can be used by a BR to request to upgrade to router role. If there are fewer routers than "router upgrade threshold" leader will accept the request. If the number of routers is more than the threshold but less than max, the leader will accept the BR request only if the number of current Border Routers (as indicated by Network Data) that are acting as router is less than two (thus allowing up to two BRs to use this status reason to become router when already above the threshold). The other change in this PR, is that when processing Address Solicit request if the included status value is not known or invalid, a response with `kUnrecognizedStatus` status is sent.
This commit is contained in:
@@ -3803,11 +3803,12 @@ void MleRouter::HandleAddressSolicit(void *aContext, otMessage *aMessage, const
|
||||
|
||||
void MleRouter::HandleAddressSolicit(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Mac::ExtAddress extAddress;
|
||||
uint16_t rloc16;
|
||||
uint8_t status;
|
||||
Router * router = nullptr;
|
||||
Error error = kErrorNone;
|
||||
ThreadStatusTlv::Status responseStatus = ThreadStatusTlv::kNoAddressAvailable;
|
||||
Router * router = nullptr;
|
||||
Mac::ExtAddress extAddress;
|
||||
uint16_t rloc16;
|
||||
uint8_t status;
|
||||
|
||||
VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = kErrorParse);
|
||||
|
||||
@@ -3816,6 +3817,17 @@ void MleRouter::HandleAddressSolicit(Coap::Message &aMessage, const Ip6::Message
|
||||
SuccessOrExit(error = Tlv::Find<ThreadExtMacAddressTlv>(aMessage, extAddress));
|
||||
SuccessOrExit(error = Tlv::Find<ThreadStatusTlv>(aMessage, status));
|
||||
|
||||
switch (Tlv::Find<ThreadRloc16Tlv>(aMessage, rloc16))
|
||||
{
|
||||
case kErrorNone:
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
rloc16 = Mac::kShortAddrInvalid;
|
||||
break;
|
||||
default:
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
{
|
||||
uint16_t xtalAccuracy;
|
||||
@@ -3827,7 +3839,12 @@ void MleRouter::HandleAddressSolicit(Coap::Message &aMessage, const Ip6::Message
|
||||
|
||||
// Check if allocation already exists
|
||||
router = mRouterTable.GetRouter(extAddress);
|
||||
VerifyOrExit(router == nullptr);
|
||||
|
||||
if (router != nullptr)
|
||||
{
|
||||
responseStatus = ThreadStatusTlv::kSuccess;
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
@@ -3839,61 +3856,61 @@ void MleRouter::HandleAddressSolicit(Coap::Message &aMessage, const Ip6::Message
|
||||
case ThreadStatusTlv::kParentPartitionChange:
|
||||
break;
|
||||
|
||||
case ThreadStatusTlv::kBorderRouterRequst:
|
||||
if ((mRouterTable.GetActiveRouterCount() >= mRouterUpgradeThreshold) &&
|
||||
(Get<NetworkData::Leader>().CountBorderRouters(NetworkData::kRouterRoleOnly) >=
|
||||
kRouterUpgradeBorderRouterRequestThreshold))
|
||||
{
|
||||
LogInfo("Rejecting BR %s router role req - have %d BR routers", extAddress.ToString().AsCString(),
|
||||
kRouterUpgradeBorderRouterRequestThreshold);
|
||||
ExitNow();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(error = kErrorParse);
|
||||
responseStatus = ThreadStatusTlv::kUnrecognizedStatus;
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
switch (Tlv::Find<ThreadRloc16Tlv>(aMessage, rloc16))
|
||||
if (rloc16 != Mac::kShortAddrInvalid)
|
||||
{
|
||||
case kErrorNone:
|
||||
router = mRouterTable.Allocate(RouterIdFromRloc16(rloc16));
|
||||
|
||||
if (router != nullptr)
|
||||
{
|
||||
LogInfo("Router id %d requested and provided!", RouterIdFromRloc16(rloc16));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OT_FALL_THROUGH;
|
||||
|
||||
case kErrorNotFound:
|
||||
if (router == nullptr)
|
||||
{
|
||||
router = mRouterTable.Allocate();
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(error = kErrorParse);
|
||||
VerifyOrExit(router != nullptr);
|
||||
}
|
||||
|
||||
if (router != nullptr)
|
||||
{
|
||||
router->SetExtAddress(extAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo("Router address unavailable!");
|
||||
}
|
||||
router->SetExtAddress(extAddress);
|
||||
responseStatus = ThreadStatusTlv::kSuccess;
|
||||
|
||||
exit:
|
||||
if (error == kErrorNone)
|
||||
{
|
||||
SendAddressSolicitResponse(aMessage, router, aMessageInfo);
|
||||
SendAddressSolicitResponse(aMessage, responseStatus, router, aMessageInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void MleRouter::SendAddressSolicitResponse(const Coap::Message & aRequest,
|
||||
ThreadStatusTlv::Status aResponseStatus,
|
||||
const Router * aRouter,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Coap::Message * message = Get<Tmf::Agent>().NewPriorityMessage();
|
||||
ThreadStatusTlv::Status status;
|
||||
Coap::Message *message = Get<Tmf::Agent>().NewPriorityMessage();
|
||||
|
||||
VerifyOrExit(message != nullptr);
|
||||
|
||||
SuccessOrExit(message->SetDefaultResponseHeader(aRequest));
|
||||
SuccessOrExit(message->SetPayloadMarker());
|
||||
|
||||
status = (aRouter == nullptr) ? ThreadStatusTlv::kNoAddressAvailable : ThreadStatusTlv::kSuccess;
|
||||
SuccessOrExit(Tlv::Append<ThreadStatusTlv>(*message, status));
|
||||
SuccessOrExit(Tlv::Append<ThreadStatusTlv>(*message, aResponseStatus));
|
||||
|
||||
if (aRouter != nullptr)
|
||||
{
|
||||
|
||||
@@ -575,6 +575,11 @@ private:
|
||||
static constexpr uint32_t kStateUpdatePeriod = 1000; // State update period (in msec).
|
||||
static constexpr uint16_t kUnsolicitedDataResponseJitter = 500; // Max delay for unsol Data Response (in msec).
|
||||
|
||||
// Threshold to accept a router upgrade request with reason
|
||||
// `kBorderRouterRequst` (number of BRs acting as router in
|
||||
// Network Data).
|
||||
static constexpr uint8_t kRouterUpgradeBorderRouterRequestThreshold = 2;
|
||||
|
||||
Error AppendConnectivity(Message &aMessage);
|
||||
Error AppendChildAddresses(Message &aMessage, Child &aChild);
|
||||
Error AppendRoute(Message &aMessage, Neighbor *aNeighbor = nullptr);
|
||||
@@ -616,6 +621,7 @@ private:
|
||||
Error SendAddressSolicit(ThreadStatusTlv::Status aStatus);
|
||||
void SendAddressRelease(void);
|
||||
void SendAddressSolicitResponse(const Coap::Message & aRequest,
|
||||
ThreadStatusTlv::Status aResponseStatus,
|
||||
const Router * aRouter,
|
||||
const Ip6::MessageInfo &aMessageInfo);
|
||||
void SendAdvertisement(void);
|
||||
|
||||
@@ -166,6 +166,8 @@ public:
|
||||
kTooFewRouters = 2, ///< Address Solicit due to too few routers.
|
||||
kHaveChildIdRequest = 3, ///< Address Solicit due to child ID request.
|
||||
kParentPartitionChange = 4, ///< Address Solicit due to parent partition change
|
||||
kBorderRouterRequst = 5, ///< Address Solicit from Border Router request.
|
||||
kUnrecognizedStatus = 6, ///< The requested status is unrecognized or not meaningful in a request.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user