| /* |
| * Copyright (c) 2016-2017, 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 the OpenThread Instance class. |
| */ |
| |
| #include "instance.hpp" |
| |
| #include <openthread/platform/misc.h> |
| |
| #include "common/new.hpp" |
| #include "radio/trel_link.hpp" |
| #include "utils/heap.hpp" |
| |
| namespace ot { |
| |
| #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE |
| |
| // Define the raw storage used for OpenThread instance (in single-instance case). |
| OT_DEFINE_ALIGNED_VAR(gInstanceRaw, sizeof(Instance), uint64_t); |
| |
| #endif |
| |
| #if OPENTHREAD_MTD || OPENTHREAD_FTD |
| #if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE |
| Utils::Heap Instance::sHeap; |
| #endif |
| #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE |
| bool Instance::sDnsNameCompressionEnabled = true; |
| #endif |
| #endif |
| |
| #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE |
| LogLevel Instance::sLogLevel = static_cast<LogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL_INIT); |
| #endif |
| |
| Instance::Instance(void) |
| : mTimerMilliScheduler(*this) |
| #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE |
| , mTimerMicroScheduler(*this) |
| #endif |
| , mRadio(*this) |
| #if OPENTHREAD_CONFIG_UPTIME_ENABLE |
| , mUptime(*this) |
| #endif |
| #if OPENTHREAD_MTD || OPENTHREAD_FTD |
| , mNotifier(*this) |
| , mTimeTicker(*this) |
| , mSettings(*this) |
| , mSettingsDriver(*this) |
| , mMessagePool(*this) |
| , mIp6(*this) |
| , mThreadNetif(*this) |
| , mTmfAgent(*this) |
| #if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE |
| , mDhcp6Client(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE |
| , mDhcp6Server(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE |
| , mNeighborDiscoveryAgent(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE |
| , mSlaac(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE |
| , mDnsClient(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE |
| , mSrpClient(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE |
| , mSrpClientBuffers(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE |
| , mDnssdServer(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_DNS_DSO_ENABLE |
| , mDnsDso(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE |
| , mSntpClient(*this) |
| #endif |
| , mActiveDataset(*this) |
| , mPendingDataset(*this) |
| , mExtendedPanIdManager(*this) |
| , mNetworkNameManager(*this) |
| , mIp6Filter(*this) |
| , mKeyManager(*this) |
| , mLowpan(*this) |
| , mMac(*this) |
| , mMeshForwarder(*this) |
| , mMleRouter(*this) |
| , mDiscoverScanner(*this) |
| , mAddressResolver(*this) |
| #if OPENTHREAD_CONFIG_MULTI_RADIO |
| , mRadioSelector(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE |
| , mNetworkDataLocal(*this) |
| #endif |
| , mNetworkDataLeader(*this) |
| #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE |
| , mNetworkDataNotifier(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE |
| , mNetworkDataPublisher(*this) |
| #endif |
| , mNetworkDataServiceManager(*this) |
| #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE |
| , mNetworkDiagnostic(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE |
| , mBorderAgent(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD |
| , mCommissioner(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_DTLS_ENABLE |
| , mCoapSecure(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_JOINER_ENABLE |
| , mJoiner(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE |
| , mJamDetector(*this) |
| #endif |
| #if OPENTHREAD_FTD |
| , mJoinerRouter(*this) |
| , mLeader(*this) |
| #endif |
| #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) |
| , mBackboneRouterLeader(*this) |
| #endif |
| #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE |
| , mBackboneRouterLocal(*this) |
| , mBackboneRouterManager(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) |
| , mMlrManager(*this) |
| #endif |
| |
| #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE) |
| , mDuaManager(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE |
| , mSrpServer(*this) |
| #endif |
| |
| #if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE |
| #if OPENTHREAD_FTD |
| , mChildSupervisor(*this) |
| #endif |
| , mSupervisionListener(*this) |
| #endif |
| , mAnnounceBegin(*this) |
| , mPanIdQuery(*this) |
| , mEnergyScan(*this) |
| #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE |
| , mAnycastLocator(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE |
| , mTimeSync(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE |
| , mLinkMetrics(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_COAP_API_ENABLE |
| , mApplicationCoap(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE |
| , mApplicationCoapSecure(*this, /* aLayerTwoSecurity */ true) |
| #endif |
| #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE |
| , mPingSender(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE |
| , mChannelMonitor(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD |
| , mChannelManager(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE |
| , mHistoryTracker(*this) |
| #endif |
| #if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD |
| , mDatasetUpdater(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE |
| , mAnnounceSender(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_OTNS_ENABLE |
| , mOtns(*this) |
| #endif |
| #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE |
| , mRoutingManager(*this) |
| #endif |
| #endif // OPENTHREAD_MTD || OPENTHREAD_FTD |
| #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE |
| , mLinkRaw(*this) |
| #endif |
| #if OPENTHREAD_ENABLE_VENDOR_EXTENSION |
| , mExtension(Extension::ExtensionBase::Init(*this)) |
| #endif |
| #if OPENTHREAD_CONFIG_DIAG_ENABLE |
| , mDiags(*this) |
| #endif |
| , mIsInitialized(false) |
| { |
| } |
| |
| #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE |
| |
| Instance &Instance::InitSingle(void) |
| { |
| Instance *instance = &Get(); |
| |
| VerifyOrExit(!instance->mIsInitialized); |
| |
| instance = new (&gInstanceRaw) Instance(); |
| |
| instance->AfterInit(); |
| |
| exit: |
| return *instance; |
| } |
| |
| Instance &Instance::Get(void) |
| { |
| void *instance = &gInstanceRaw; |
| |
| return *static_cast<Instance *>(instance); |
| } |
| |
| #else // #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE |
| |
| Instance *Instance::Init(void *aBuffer, size_t *aBufferSize) |
| { |
| Instance *instance = nullptr; |
| |
| VerifyOrExit(aBufferSize != nullptr); |
| |
| // Make sure the input buffer is big enough |
| VerifyOrExit(sizeof(Instance) <= *aBufferSize, *aBufferSize = sizeof(Instance)); |
| |
| VerifyOrExit(aBuffer != nullptr); |
| |
| instance = new (aBuffer) Instance(); |
| |
| instance->AfterInit(); |
| |
| exit: |
| return instance; |
| } |
| |
| #endif // OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE |
| |
| void Instance::Reset(void) |
| { |
| otPlatReset(this); |
| } |
| |
| #if OPENTHREAD_RADIO |
| void Instance::ResetRadioStack(void) |
| { |
| mRadio.Init(); |
| mLinkRaw.Init(); |
| } |
| #endif |
| |
| void Instance::AfterInit(void) |
| { |
| mIsInitialized = true; |
| #if OPENTHREAD_MTD || OPENTHREAD_FTD |
| |
| // Restore datasets and network information |
| |
| Get<Settings>().Init(); |
| Get<Mle::MleRouter>().Restore(); |
| |
| #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE |
| Get<Trel::Link>().AfterInit(); |
| #endif |
| |
| #endif // OPENTHREAD_MTD || OPENTHREAD_FTD |
| |
| #if OPENTHREAD_ENABLE_VENDOR_EXTENSION |
| Get<Extension::ExtensionBase>().SignalInstanceInit(); |
| #endif |
| } |
| |
| void Instance::Finalize(void) |
| { |
| VerifyOrExit(mIsInitialized); |
| |
| mIsInitialized = false; |
| |
| #if OPENTHREAD_MTD || OPENTHREAD_FTD |
| IgnoreError(otThreadSetEnabled(this, false)); |
| IgnoreError(otIp6SetEnabled(this, false)); |
| IgnoreError(otLinkSetEnabled(this, false)); |
| |
| Get<Settings>().Deinit(); |
| #endif |
| |
| IgnoreError(Get<Mac::SubMac>().Disable()); |
| |
| #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE |
| |
| /** |
| * Object was created on buffer, so instead of deleting |
| * the object we call destructor explicitly. |
| */ |
| this->~Instance(); |
| |
| #endif // !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE |
| |
| exit: |
| return; |
| } |
| |
| #if OPENTHREAD_MTD || OPENTHREAD_FTD |
| |
| void Instance::FactoryReset(void) |
| { |
| Get<Settings>().Wipe(); |
| otPlatReset(this); |
| } |
| |
| Error Instance::ErasePersistentInfo(void) |
| { |
| Error error = kErrorNone; |
| |
| VerifyOrExit(Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState); |
| Get<Settings>().Wipe(); |
| |
| exit: |
| return error; |
| } |
| |
| void Instance::GetBufferInfo(BufferInfo &aInfo) |
| { |
| aInfo.Clear(); |
| |
| aInfo.mTotalBuffers = Get<MessagePool>().GetTotalBufferCount(); |
| aInfo.mFreeBuffers = Get<MessagePool>().GetFreeBufferCount(); |
| |
| Get<MeshForwarder>().GetSendQueue().GetInfo(aInfo.m6loSendQueue); |
| Get<MeshForwarder>().GetReassemblyQueue().GetInfo(aInfo.m6loReassemblyQueue); |
| Get<Ip6::Ip6>().GetSendQueue().GetInfo(aInfo.mIp6Queue); |
| |
| #if OPENTHREAD_FTD |
| Get<Ip6::Mpl>().GetBufferedMessageSet().GetInfo(aInfo.mMplQueue); |
| #endif |
| |
| Get<Mle::MleRouter>().GetMessageQueue().GetInfo(aInfo.mMleQueue); |
| |
| Get<Tmf::Agent>().GetRequestMessages().GetInfo(aInfo.mCoapQueue); |
| Get<Tmf::Agent>().GetCachedResponses().GetInfo(aInfo.mCoapQueue); |
| |
| #if OPENTHREAD_CONFIG_DTLS_ENABLE |
| Get<Coap::CoapSecure>().GetRequestMessages().GetInfo(aInfo.mCoapSecureQueue); |
| Get<Coap::CoapSecure>().GetCachedResponses().GetInfo(aInfo.mCoapSecureQueue); |
| #endif |
| |
| #if OPENTHREAD_CONFIG_COAP_API_ENABLE |
| GetApplicationCoap().GetRequestMessages().GetInfo(aInfo.mApplicationCoapQueue); |
| GetApplicationCoap().GetCachedResponses().GetInfo(aInfo.mApplicationCoapQueue); |
| #endif |
| } |
| |
| #endif // OPENTHREAD_MTD || OPENTHREAD_FTD |
| |
| #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE |
| |
| void Instance::SetLogLevel(LogLevel aLogLevel) |
| { |
| if (aLogLevel != sLogLevel) |
| { |
| sLogLevel = aLogLevel; |
| otPlatLogHandleLevelChanged(sLogLevel); |
| } |
| } |
| |
| extern "C" OT_TOOL_WEAK void otPlatLogHandleLevelChanged(otLogLevel aLogLevel) |
| { |
| OT_UNUSED_VARIABLE(aLogLevel); |
| } |
| |
| #endif |
| |
| } // namespace ot |