[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:
Abtin Keshavarzian
2022-04-14 09:57:39 -07:00
committed by GitHub
parent ba5ebc7296
commit 73f28712b2
3 changed files with 55 additions and 30 deletions
+47 -30
View File
@@ -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)
{
+6
View File
@@ -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);
+2
View File
@@ -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.
};
/**