1 /*
2  *  Copyright (c) 2016-2017, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file implements the OpenThread Instance class.
32  */
33 
34 #include "instance.hpp"
35 
36 #include <openthread/platform/misc.h>
37 
38 #include "common/new.hpp"
39 #include "utils/heap.hpp"
40 
41 namespace ot {
42 
43 #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
44 
45 // Define the raw storage used for OpenThread instance (in single-instance case).
46 OT_DEFINE_ALIGNED_VAR(gInstanceRaw, sizeof(Instance), uint64_t);
47 
48 #endif
49 
50 #if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
51 
52 #define INSTANCE_SIZE_ALIGNED OT_ALIGNED_VAR_SIZE(sizeof(ot::Instance), uint64_t)
53 #define MULTI_INSTANCE_SIZE (OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM * INSTANCE_SIZE_ALIGNED)
54 
55 // Define the raw storage used for OpenThread instance (in multi-instance case).
56 static uint64_t gMultiInstanceRaw[MULTI_INSTANCE_SIZE];
57 
58 #endif
59 
60 #if OPENTHREAD_MTD || OPENTHREAD_FTD
61 #if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
62 OT_DEFINE_ALIGNED_VAR(sHeapRaw, sizeof(Utils::Heap), uint64_t);
63 Utils::Heap *Instance::sHeap{nullptr};
64 #endif
65 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
66 bool Instance::sDnsNameCompressionEnabled = true;
67 #endif
68 #endif
69 
70 #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
71 LogLevel Instance::sLogLevel = static_cast<LogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL_INIT);
72 #endif
73 
Instance(void)74 Instance::Instance(void)
75     : mTimerMilliScheduler(*this)
76 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
77     , mTimerMicroScheduler(*this)
78 #endif
79 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
80     , mCryptoStorageKeyRefManager(*this)
81 #endif
82     , mRadio(*this)
83 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
84     , mUptime(*this)
85 #endif
86 #if OPENTHREAD_MTD || OPENTHREAD_FTD
87     , mNotifier(*this)
88     , mTimeTicker(*this)
89     , mSettings(*this)
90     , mSettingsDriver(*this)
91     , mMessagePool(*this)
92 #if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE || OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE
93     // DNS-SD (mDNS) platform is initialized early to
94     // allow other modules to use it.
95     , mDnssd(*this)
96 #endif
97     , mIp6(*this)
98     , mThreadNetif(*this)
99     , mTmfAgent(*this)
100 #if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
101     , mDhcp6Client(*this)
102 #endif
103 #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
104     , mDhcp6Server(*this)
105 #endif
106 #if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
107     , mNeighborDiscoveryAgent(*this)
108 #endif
109 #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
110     , mSlaac(*this)
111 #endif
112 #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
113     , mDnsClient(*this)
114 #endif
115 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
116     , mSrpClient(*this)
117 #endif
118 #if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
119     , mSrpClientBuffers(*this)
120 #endif
121 #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
122     , mDnssdServer(*this)
123 #endif
124 #if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
125     , mDnsDso(*this)
126 #endif
127 #if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE
128     , mMdnsCore(*this)
129 #endif
130 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
131     , mSntpClient(*this)
132 #endif
133 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
134     , mBackboneRouterLocal(*this)
135 #endif
136     , mActiveDataset(*this)
137     , mPendingDataset(*this)
138     , mExtendedPanIdManager(*this)
139     , mNetworkNameManager(*this)
140     , mIp6Filter(*this)
141     , mKeyManager(*this)
142     , mLowpan(*this)
143     , mMac(*this)
144     , mMeshForwarder(*this)
145     , mMleRouter(*this)
146     , mDiscoverScanner(*this)
147     , mAddressResolver(*this)
148 #if OPENTHREAD_CONFIG_MULTI_RADIO
149     , mRadioSelector(*this)
150 #endif
151 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
152     , mNetworkDataLocal(*this)
153 #endif
154     , mNetworkDataLeader(*this)
155 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
156     , mNetworkDataNotifier(*this)
157 #endif
158 #if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
159     , mNetworkDataPublisher(*this)
160 #endif
161     , mNetworkDataServiceManager(*this)
162     , mNetworkDiagnosticServer(*this)
163 #if OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE
164     , mNetworkDiagnosticClient(*this)
165 #endif
166 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
167     , mBorderAgent(*this)
168 #endif
169 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
170     , mCommissioner(*this)
171 #endif
172 #if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
173     , mTmfSecureAgent(*this)
174 #endif
175 #if OPENTHREAD_CONFIG_JOINER_ENABLE
176     , mJoiner(*this)
177 #endif
178 #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
179     , mJamDetector(*this)
180 #endif
181 #if OPENTHREAD_FTD
182     , mJoinerRouter(*this)
183     , mLeader(*this)
184 #endif
185 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
186     , mBackboneRouterLeader(*this)
187 #endif
188 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
189     , mBackboneRouterManager(*this)
190 #endif
191 #if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
192     , mMlrManager(*this)
193 #endif
194 
195 #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
196     , mDuaManager(*this)
197 #endif
198 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
199     , mSrpServer(*this)
200 #if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
201     , mSrpAdvertisingProxy(*this)
202 #endif
203 #endif
204 #if OPENTHREAD_FTD
205     , mChildSupervisor(*this)
206 #endif
207     , mSupervisionListener(*this)
208     , mAnnounceBegin(*this)
209     , mPanIdQuery(*this)
210     , mEnergyScan(*this)
211 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
212     , mAnycastLocator(*this)
213 #endif
214 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
215     , mTimeSync(*this)
216 #endif
217 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
218     , mInitiator(*this)
219 #endif
220 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
221     , mSubject(*this)
222 #endif
223 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
224     , mApplicationCoap(*this)
225 #endif
226 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
227     , mApplicationCoapSecure(*this, kWithLinkSecurity)
228 #endif
229 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
230     , mApplicationBleSecure(*this)
231 #endif
232 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
233     , mPingSender(*this)
234 #endif
235 #if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
236     , mChannelMonitor(*this)
237 #endif
238 #if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && \
239     (OPENTHREAD_FTD || OPENTHREAD_CONFIG_CHANNEL_MANAGER_CSL_CHANNEL_SELECT_ENABLE)
240     , mChannelManager(*this)
241 #endif
242 #if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
243     , mMeshDiag(*this)
244 #endif
245 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
246     , mHistoryTracker(*this)
247 #endif
248 #if OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
249     , mLinkMetricsManager(*this)
250 #endif
251 #if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
252     , mDatasetUpdater(*this)
253 #endif
254 #if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
255     , mAnnounceSender(*this)
256 #endif
257 #if OPENTHREAD_CONFIG_OTNS_ENABLE
258     , mOtns(*this)
259 #endif
260 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
261     , mRoutingManager(*this)
262 #endif
263 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
264     , mNat64Translator(*this)
265 #endif
266 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
267 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
268     , mLinkRaw(*this)
269 #endif
270 #if OPENTHREAD_ENABLE_VENDOR_EXTENSION
271     , mExtension(Extension::ExtensionBase::Init(*this))
272 #endif
273 #if OPENTHREAD_CONFIG_DIAG_ENABLE
274     , mDiags(*this)
275 #endif
276 #if OPENTHREAD_CONFIG_POWER_CALIBRATION_ENABLE && OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
277     , mPowerCalibration(*this)
278 #endif
279     , mIsInitialized(false)
280     , mId(Random::NonCrypto::GetUint32())
281 {
282 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
283 #if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
284     mCryptoStorageKeyRefManager.SetKeyRefExtraOffset(Crypto::Storage::KeyRefManager::kKeyRefExtraOffset * GetIdx(this));
285 #else
286 #error "MULTIPLE_INSTANCE (without static allocation) is used with PLATFORM_KEY_REFERENCES_ENABLE " \
287        "The `KeyRef` values will be shared across different `Instance` objects"
288 #endif
289 #endif
290 }
291 
292 #if (OPENTHREAD_MTD || OPENTHREAD_FTD) && !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
GetHeap(void)293 Utils::Heap &Instance::GetHeap(void)
294 {
295     if (nullptr == sHeap)
296     {
297         sHeap = new (&sHeapRaw) Utils::Heap();
298     }
299 
300     return *sHeap;
301 }
302 #endif
303 
304 #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
305 
InitSingle(void)306 Instance &Instance::InitSingle(void)
307 {
308     Instance *instance = &Get();
309 
310     VerifyOrExit(!instance->mIsInitialized);
311 
312     instance = new (&gInstanceRaw) Instance();
313 
314     instance->AfterInit();
315 
316 exit:
317     return *instance;
318 }
319 
Get(void)320 Instance &Instance::Get(void)
321 {
322     void *instance = &gInstanceRaw;
323 
324     return *static_cast<Instance *>(instance);
325 }
326 
327 #else // #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
328 #if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
329 
InitMultiple(uint8_t aIdx)330 Instance *Instance::InitMultiple(uint8_t aIdx)
331 {
332     size_t    bufferSize;
333     uint64_t *instanceBuffer = gMultiInstanceRaw + aIdx * INSTANCE_SIZE_ALIGNED;
334     Instance *instance       = reinterpret_cast<Instance *>(instanceBuffer);
335 
336     VerifyOrExit(aIdx < OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
337     VerifyOrExit(!instance->mIsInitialized);
338 
339     bufferSize = (&gMultiInstanceRaw[MULTI_INSTANCE_SIZE] - instanceBuffer) * sizeof(uint64_t);
340     instance   = Instance::Init(instanceBuffer, &bufferSize);
341 
342 exit:
343     return instance;
344 }
345 
Get(uint8_t aIdx)346 Instance &Instance::Get(uint8_t aIdx)
347 {
348     void *instance = gMultiInstanceRaw + aIdx * INSTANCE_SIZE_ALIGNED;
349     return *static_cast<Instance *>(instance);
350 }
351 
GetIdx(Instance * aInstance)352 uint8_t Instance::GetIdx(Instance *aInstance)
353 {
354     return static_cast<uint8_t>((reinterpret_cast<uint64_t *>(aInstance) - gMultiInstanceRaw) / INSTANCE_SIZE_ALIGNED);
355 }
356 
357 #endif // #if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
358 
Init(void * aBuffer,size_t * aBufferSize)359 Instance *Instance::Init(void *aBuffer, size_t *aBufferSize)
360 {
361     Instance *instance = nullptr;
362 
363     VerifyOrExit(aBufferSize != nullptr);
364 
365     // Make sure the input buffer is big enough
366     VerifyOrExit(sizeof(Instance) <= *aBufferSize, *aBufferSize = sizeof(Instance));
367 
368     VerifyOrExit(aBuffer != nullptr);
369 
370     instance = new (aBuffer) Instance();
371 
372     instance->AfterInit();
373 
374 exit:
375     return instance;
376 }
377 
378 #endif // OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
379 
Reset(void)380 void Instance::Reset(void) { otPlatReset(this); }
381 
382 #if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
ResetToBootloader(void)383 Error Instance::ResetToBootloader(void) { return otPlatResetToBootloader(this); }
384 #endif
385 
386 #if OPENTHREAD_RADIO
ResetRadioStack(void)387 void Instance::ResetRadioStack(void)
388 {
389     mRadio.Init();
390     mLinkRaw.Init();
391 }
392 #endif
393 
AfterInit(void)394 void Instance::AfterInit(void)
395 {
396     mIsInitialized = true;
397 #if OPENTHREAD_MTD || OPENTHREAD_FTD
398 
399     // Restore datasets and network information
400 
401     Get<Settings>().Init();
402     Get<Mle::MleRouter>().Restore();
403 
404 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
405     Get<Trel::Link>().AfterInit();
406 #endif
407 
408 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
409 
410 #if OPENTHREAD_ENABLE_VENDOR_EXTENSION
411     Get<Extension::ExtensionBase>().SignalInstanceInit();
412 #endif
413 }
414 
Finalize(void)415 void Instance::Finalize(void)
416 {
417     VerifyOrExit(mIsInitialized);
418 
419     mIsInitialized = false;
420 
421 #if OPENTHREAD_MTD || OPENTHREAD_FTD
422     IgnoreError(otThreadSetEnabled(this, false));
423     IgnoreError(otIp6SetEnabled(this, false));
424     IgnoreError(otLinkSetEnabled(this, false));
425 
426 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
427     Get<KeyManager>().DestroyTemporaryKeys();
428 #endif
429 
430     Get<Settings>().Deinit();
431 #endif
432 
433     IgnoreError(Get<Mac::SubMac>().Disable());
434 
435 #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
436 
437     /**
438      * Object was created on buffer, so instead of deleting
439      * the object we call destructor explicitly.
440      */
441     this->~Instance();
442 
443 #endif // !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
444 
445 exit:
446     return;
447 }
448 
449 #if OPENTHREAD_MTD || OPENTHREAD_FTD
450 
FactoryReset(void)451 void Instance::FactoryReset(void)
452 {
453     Get<Settings>().Wipe();
454 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
455     Get<KeyManager>().DestroyTemporaryKeys();
456     Get<KeyManager>().DestroyPersistentKeys();
457 #endif
458     otPlatReset(this);
459 }
460 
ErasePersistentInfo(void)461 Error Instance::ErasePersistentInfo(void)
462 {
463     Error error = kErrorNone;
464 
465     VerifyOrExit(Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
466     Get<Settings>().Wipe();
467 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
468     Get<KeyManager>().DestroyTemporaryKeys();
469     Get<KeyManager>().DestroyPersistentKeys();
470 #endif
471 
472 exit:
473     return error;
474 }
475 
GetBufferInfo(BufferInfo & aInfo)476 void Instance::GetBufferInfo(BufferInfo &aInfo)
477 {
478     aInfo.Clear();
479 
480     aInfo.mTotalBuffers   = Get<MessagePool>().GetTotalBufferCount();
481     aInfo.mFreeBuffers    = Get<MessagePool>().GetFreeBufferCount();
482     aInfo.mMaxUsedBuffers = Get<MessagePool>().GetMaxUsedBufferCount();
483 
484     Get<MeshForwarder>().GetSendQueue().GetInfo(aInfo.m6loSendQueue);
485     Get<MeshForwarder>().GetReassemblyQueue().GetInfo(aInfo.m6loReassemblyQueue);
486     Get<Ip6::Ip6>().GetSendQueue().GetInfo(aInfo.mIp6Queue);
487 
488 #if OPENTHREAD_FTD
489     Get<Ip6::Mpl>().GetBufferedMessageSet().GetInfo(aInfo.mMplQueue);
490 #endif
491 
492     Get<Mle::MleRouter>().GetMessageQueue().GetInfo(aInfo.mMleQueue);
493 
494     Get<Tmf::Agent>().GetRequestMessages().GetInfo(aInfo.mCoapQueue);
495     Get<Tmf::Agent>().GetCachedResponses().GetInfo(aInfo.mCoapQueue);
496 
497 #if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
498     Get<Tmf::SecureAgent>().GetRequestMessages().GetInfo(aInfo.mCoapSecureQueue);
499     Get<Tmf::SecureAgent>().GetCachedResponses().GetInfo(aInfo.mCoapSecureQueue);
500 #endif
501 
502 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
503     GetApplicationCoap().GetRequestMessages().GetInfo(aInfo.mApplicationCoapQueue);
504     GetApplicationCoap().GetCachedResponses().GetInfo(aInfo.mApplicationCoapQueue);
505 #endif
506 }
507 
ResetBufferInfo(void)508 void Instance::ResetBufferInfo(void) { Get<MessagePool>().ResetMaxUsedBufferCount(); }
509 
510 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
511 
512 #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
513 
SetLogLevel(LogLevel aLogLevel)514 void Instance::SetLogLevel(LogLevel aLogLevel)
515 {
516     if (aLogLevel != sLogLevel)
517     {
518         sLogLevel = aLogLevel;
519         otPlatLogHandleLevelChanged(sLogLevel);
520     }
521 }
522 
otPlatLogHandleLevelChanged(otLogLevel aLogLevel)523 extern "C" OT_TOOL_WEAK void otPlatLogHandleLevelChanged(otLogLevel aLogLevel) { OT_UNUSED_VARIABLE(aLogLevel); }
524 
525 #endif
526 
527 } // namespace ot
528