/* * Copyright (c) 2019, 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 Primary Backbone Router service management in the Thread Network. */ #include "bbr_leader.hpp" #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) #include "common/instance.hpp" #include "common/locator_getters.hpp" namespace ot { namespace BackboneRouter { RegisterLogModule("BbrLeader"); Leader::Leader(Instance &aInstance) : InstanceLocator(aInstance) { Reset(); } void Leader::Reset(void) { // Invalid server short address indicates no available Backbone Router service in the Thread Network. mConfig.mServer16 = Mac::kShortAddrInvalid; // Domain Prefix Length 0 indicates no available Domain Prefix in the Thread network. mDomainPrefix.SetLength(0); } Error Leader::GetConfig(BackboneRouterConfig &aConfig) const { Error error = kErrorNone; VerifyOrExit(HasPrimary(), error = kErrorNotFound); aConfig = mConfig; exit: return error; } Error Leader::GetServiceId(uint8_t &aServiceId) const { Error error = kErrorNone; VerifyOrExit(HasPrimary(), error = kErrorNotFound); error = Get().GetServiceId( /* aServerStable */ true, aServiceId); exit: return error; } #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) void Leader::LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &aConfig) const { OT_UNUSED_VARIABLE(aConfig); LogInfo("PBBR state: %s", StateToString(aState)); if (aState != kStateRemoved && aState != kStateNone) { LogInfo("Rloc16: 0x%4X, seqno: %d, delay: %d, timeout %d", aConfig.mServer16, aConfig.mSequenceNumber, aConfig.mReregistrationDelay, aConfig.mMlrTimeout); } } void Leader::LogDomainPrefix(DomainPrefixState aState, const Ip6::Prefix &aPrefix) const { LogInfo("Domain Prefix: %s, state: %s", aPrefix.ToString().AsCString(), DomainPrefixStateToString(aState)); } const char *Leader::StateToString(State aState) { static const char *const kStateStrings[] = { "None", // (0) kStateNone "Added", // (1) kStateAdded "Removed", // (2) kStateRemoved "Rereg triggered", // (3) kStateToTriggerRereg "Refreshed", // (4) kStateRefreshed "Unchanged", // (5) kStateUnchanged }; static_assert(0 == kStateNone, "kStateNone value is incorrect"); static_assert(1 == kStateAdded, "kStateAdded value is incorrect"); static_assert(2 == kStateRemoved, "kStateRemoved value is incorrect"); static_assert(3 == kStateToTriggerRereg, "kStateToTriggerRereg value is incorrect"); static_assert(4 == kStateRefreshed, "kStateRefreshed value is incorrect"); static_assert(5 == kStateUnchanged, "kStateUnchanged value is incorrect"); return kStateStrings[aState]; } const char *Leader::DomainPrefixStateToString(DomainPrefixState aState) { static const char *const kPrefixStateStrings[] = { "None", // (0) kDomainPrefixNone "Added", // (1) kDomainPrefixAdded "Removed", // (2) kDomainPrefixRemoved "Refreshed", // (3) kDomainPrefixRefreshed "Unchanged", // (4) kDomainPrefixUnchanged }; static_assert(0 == kDomainPrefixNone, "kDomainPrefixNone value is incorrect"); static_assert(1 == kDomainPrefixAdded, "kDomainPrefixAdded value is incorrect"); static_assert(2 == kDomainPrefixRemoved, "kDomainPrefixRemoved value is incorrect"); static_assert(3 == kDomainPrefixRefreshed, "kDomainPrefixRefreshed value is incorrect"); static_assert(4 == kDomainPrefixUnchanged, "kDomainPrefixUnchanged value is incorrect"); return kPrefixStateStrings[aState]; } #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) void Leader::Update(void) { UpdateBackboneRouterPrimary(); UpdateDomainPrefixConfig(); } void Leader::UpdateBackboneRouterPrimary(void) { BackboneRouterConfig config; State state; uint32_t origMlrTimeout; Get().GetBackboneRouterPrimary(config); if (config.mServer16 != mConfig.mServer16) { if (config.mServer16 == Mac::kShortAddrInvalid) { state = kStateRemoved; } else if (mConfig.mServer16 == Mac::kShortAddrInvalid) { state = kStateAdded; } else { // Short Address of PBBR changes. state = kStateToTriggerRereg; } } else if (config.mServer16 == Mac::kShortAddrInvalid) { // If no Primary all the time. state = kStateNone; } else if (config.mSequenceNumber != mConfig.mSequenceNumber) { state = kStateToTriggerRereg; } else if (config.mReregistrationDelay != mConfig.mReregistrationDelay || config.mMlrTimeout != mConfig.mMlrTimeout) { state = kStateRefreshed; } else { state = kStateUnchanged; } // Restrain the range of MLR timeout to be always valid if (config.mServer16 != Mac::kShortAddrInvalid) { origMlrTimeout = config.mMlrTimeout; config.mMlrTimeout = config.mMlrTimeout < static_cast(Mle::kMlrTimeoutMin) ? static_cast(Mle::kMlrTimeoutMin) : config.mMlrTimeout; config.mMlrTimeout = config.mMlrTimeout > static_cast(Mle::kMlrTimeoutMax) ? static_cast(Mle::kMlrTimeoutMax) : config.mMlrTimeout; if (config.mMlrTimeout != origMlrTimeout) { LogNote("Leader MLR Timeout is normalized from %u to %u", origMlrTimeout, config.mMlrTimeout); } } mConfig = config; LogBackboneRouterPrimary(state, mConfig); #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE Get().HandleBackboneRouterPrimaryUpdate(state, mConfig); #endif #if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) Get().HandleBackboneRouterPrimaryUpdate(state, mConfig); #endif #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) Get().HandleBackboneRouterPrimaryUpdate(state, mConfig); #endif } void Leader::UpdateDomainPrefixConfig(void) { NetworkData::Iterator iterator = NetworkData::kIteratorInit; NetworkData::OnMeshPrefixConfig config; DomainPrefixState state; bool found = false; while (Get().GetNextOnMeshPrefix(iterator, config) == kErrorNone) { if (config.mDp) { found = true; break; } } if (!found) { if (mDomainPrefix.GetLength() != 0) { // Domain Prefix does not exist any more. mDomainPrefix.SetLength(0); state = kDomainPrefixRemoved; } else { state = kDomainPrefixNone; } } else if (config.GetPrefix() == mDomainPrefix) { state = kDomainPrefixUnchanged; } else { if (mDomainPrefix.mLength == 0) { state = kDomainPrefixAdded; } else { state = kDomainPrefixRefreshed; } mDomainPrefix = config.GetPrefix(); } LogDomainPrefix(state, mDomainPrefix); #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE Get().HandleDomainPrefixUpdate(state); #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE Get().HandleDomainPrefixUpdate(state); #endif #endif #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) Get().HandleDomainPrefixUpdate(state); #endif } bool Leader::IsDomainUnicast(const Ip6::Address &aAddress) const { return HasDomainPrefix() && aAddress.MatchesPrefix(mDomainPrefix); } } // namespace BackboneRouter } // namespace ot #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)