diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 9485e6369..7e786ee6a 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -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(aMessage, extAddress)); SuccessOrExit(error = Tlv::Find(aMessage, status)); + switch (Tlv::Find(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().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(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().NewPriorityMessage(); - ThreadStatusTlv::Status status; + Coap::Message *message = Get().NewPriorityMessage(); VerifyOrExit(message != nullptr); SuccessOrExit(message->SetDefaultResponseHeader(aRequest)); SuccessOrExit(message->SetPayloadMarker()); - status = (aRouter == nullptr) ? ThreadStatusTlv::kNoAddressAvailable : ThreadStatusTlv::kSuccess; - SuccessOrExit(Tlv::Append(*message, status)); + SuccessOrExit(Tlv::Append(*message, aResponseStatus)); if (aRouter != nullptr) { diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 362e76bfb..3de82684a 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -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); diff --git a/src/core/thread/thread_tlvs.hpp b/src/core/thread/thread_tlvs.hpp index 0e5b5daae..24eb9193b 100644 --- a/src/core/thread/thread_tlvs.hpp +++ b/src/core/thread/thread_tlvs.hpp @@ -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. }; /**