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 "radio/trel_link.hpp"
40 #include "utils/heap.hpp"
41 
42 namespace ot {
43 
44 #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
45 
46 // Define the raw storage used for OpenThread instance (in single-instance case).
47 OT_DEFINE_ALIGNED_VAR(gInstanceRaw, sizeof(Instance), uint64_t);
48 
49 #endif
50 
51 #if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
52 
53 #define INSTANCE_SIZE_ALIGNED OT_ALIGNED_VAR_SIZE(sizeof(ot::Instance), uint64_t)
54 #define MULTI_INSTANCE_SIZE (OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM * INSTANCE_SIZE_ALIGNED)
55 
56 // Define the raw storage used for OpenThread instance (in multi-instance case).
57 static uint64_t gMultiInstanceRaw[MULTI_INSTANCE_SIZE];
58 
59 #endif
60 
61 #if OPENTHREAD_MTD || OPENTHREAD_FTD
62 #if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
63 OT_DEFINE_ALIGNED_VAR(sHeapRaw, sizeof(Utils::Heap), uint64_t);
64 Utils::Heap *Instance::sHeap{nullptr};
65 #endif
66 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
67 bool Instance::sDnsNameCompressionEnabled = true;
68 #endif
69 #endif
70 
71 #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
72 LogLevel Instance::sLogLevel = static_cast<LogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL_INIT);
73 #endif
74 
Instance(void)75 Instance::Instance(void)
76     : mTimerMilliScheduler(*this)
77 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
78     , mTimerMicroScheduler(*this)
79 #endif
80     , mRadio(*this)
81 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
82     , mUptime(*this)
83 #endif
84 #if OPENTHREAD_MTD || OPENTHREAD_FTD
85     , mNotifier(*this)
86     , mTimeTicker(*this)
87     , mSettings(*this)
88     , mSettingsDriver(*this)
89     , mMessagePool(*this)
90     , mIp6(*this)
91     , mThreadNetif(*this)
92     , mTmfAgent(*this)
93 #if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
94     , mDhcp6Client(*this)
95 #endif
96 #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
97     , mDhcp6Server(*this)
98 #endif
99 #if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
100     , mNeighborDiscoveryAgent(*this)
101 #endif
102 #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
103     , mSlaac(*this)
104 #endif
105 #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
106     , mDnsClient(*this)
107 #endif
108 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
109     , mSrpClient(*this)
110 #endif
111 #if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
112     , mSrpClientBuffers(*this)
113 #endif
114 #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
115     , mDnssdServer(*this)
116 #endif
117 #if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
118     , mDnsDso(*this)
119 #endif
120 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
121     , mSntpClient(*this)
122 #endif
123     , mActiveDataset(*this)
124     , mPendingDataset(*this)
125     , mExtendedPanIdManager(*this)
126     , mNetworkNameManager(*this)
127     , mIp6Filter(*this)
128     , mKeyManager(*this)
129     , mLowpan(*this)
130     , mMac(*this)
131     , mMeshForwarder(*this)
132     , mMleRouter(*this)
133     , mDiscoverScanner(*this)
134     , mAddressResolver(*this)
135 #if OPENTHREAD_CONFIG_MULTI_RADIO
136     , mRadioSelector(*this)
137 #endif
138 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
139     , mNetworkDataLocal(*this)
140 #endif
141     , mNetworkDataLeader(*this)
142 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
143     , mNetworkDataNotifier(*this)
144 #endif
145 #if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
146     , mNetworkDataPublisher(*this)
147 #endif
148     , mNetworkDataServiceManager(*this)
149     , mNetworkDiagnosticServer(*this)
150 #if OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE
151     , mNetworkDiagnosticClient(*this)
152 #endif
153 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
154     , mBorderAgent(*this)
155 #endif
156 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
157     , mCommissioner(*this)
158 #endif
159 #if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
160     , mTmfSecureAgent(*this)
161 #endif
162 #if OPENTHREAD_CONFIG_JOINER_ENABLE
163     , mJoiner(*this)
164 #endif
165 #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
166     , mJamDetector(*this)
167 #endif
168 #if OPENTHREAD_FTD
169     , mJoinerRouter(*this)
170     , mLeader(*this)
171 #endif
172 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
173     , mBackboneRouterLeader(*this)
174 #endif
175 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
176     , mBackboneRouterLocal(*this)
177     , mBackboneRouterManager(*this)
178 #endif
179 #if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
180     , mMlrManager(*this)
181 #endif
182 
183 #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
184     , mDuaManager(*this)
185 #endif
186 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
187     , mSrpServer(*this)
188 #endif
189 #if OPENTHREAD_FTD
190     , mChildSupervisor(*this)
191 #endif
192     , mSupervisionListener(*this)
193     , mAnnounceBegin(*this)
194     , mPanIdQuery(*this)
195     , mEnergyScan(*this)
196 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
197     , mAnycastLocator(*this)
198 #endif
199 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
200     , mTimeSync(*this)
201 #endif
202 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
203     , mInitiator(*this)
204 #endif
205 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
206     , mSubject(*this)
207 #endif
208 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
209     , mApplicationCoap(*this)
210 #endif
211 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
212     , mApplicationCoapSecure(*this, /* aLayerTwoSecurity */ true)
213 #endif
214 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
215     , mApplicationBleSecure(*this)
216 #endif
217 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
218     , mPingSender(*this)
219 #endif
220 #if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
221     , mChannelMonitor(*this)
222 #endif
223 #if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD
224     , mChannelManager(*this)
225 #endif
226 #if OPENTHREAD_CONFIG_MESH_DIAG_ENABLE && OPENTHREAD_FTD
227     , mMeshDiag(*this)
228 #endif
229 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
230     , mHistoryTracker(*this)
231 #endif
232 #if OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
233     , mLinkMetricsManager(*this)
234 #endif
235 #if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
236     , mDatasetUpdater(*this)
237 #endif
238 #if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
239     , mAnnounceSender(*this)
240 #endif
241 #if OPENTHREAD_CONFIG_OTNS_ENABLE
242     , mOtns(*this)
243 #endif
244 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
245     , mRoutingManager(*this)
246 #endif
247 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
248     , mNat64Translator(*this)
249 #endif
250 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
251 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
252     , mLinkRaw(*this)
253 #endif
254 #if OPENTHREAD_ENABLE_VENDOR_EXTENSION
255     , mExtension(Extension::ExtensionBase::Init(*this))
256 #endif
257 #if OPENTHREAD_CONFIG_DIAG_ENABLE
258     , mDiags(*this)
259 #endif
260 #if OPENTHREAD_CONFIG_POWER_CALIBRATION_ENABLE && OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
261     , mPowerCalibration(*this)
262 #endif
263     , mIsInitialized(false)
264     , mId(Random::NonCrypto::GetUint32())
265 {
266 }
267 
268 #if (OPENTHREAD_MTD || OPENTHREAD_FTD) && !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
GetHeap(void)269 Utils::Heap &Instance::GetHeap(void)
270 {
271     if (nullptr == sHeap)
272     {
273         sHeap = new (&sHeapRaw) Utils::Heap();
274     }
275 
276     return *sHeap;
277 }
278 #endif
279 
280 #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
281 
InitSingle(void)282 Instance &Instance::InitSingle(void)
283 {
284     Instance *instance = &Get();
285 
286     VerifyOrExit(!instance->mIsInitialized);
287 
288     instance = new (&gInstanceRaw) Instance();
289 
290     instance->AfterInit();
291 
292 exit:
293     return *instance;
294 }
295 
Get(void)296 Instance &Instance::Get(void)
297 {
298     void *instance = &gInstanceRaw;
299 
300     return *static_cast<Instance *>(instance);
301 }
302 
303 #else // #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
304 #if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
305 
InitMultiple(uint8_t aIdx)306 Instance *Instance::InitMultiple(uint8_t aIdx)
307 {
308     size_t    bufferSize;
309     uint64_t *instanceBuffer = gMultiInstanceRaw + aIdx * INSTANCE_SIZE_ALIGNED;
310     Instance *instance       = reinterpret_cast<Instance *>(instanceBuffer);
311 
312     VerifyOrExit(aIdx < OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
313     VerifyOrExit(!instance->mIsInitialized);
314 
315     bufferSize = (&gMultiInstanceRaw[MULTI_INSTANCE_SIZE] - instanceBuffer) * sizeof(uint64_t);
316     instance   = Instance::Init(instanceBuffer, &bufferSize);
317 
318 exit:
319     return instance;
320 }
321 
322 #endif // #if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
323 
Init(void * aBuffer,size_t * aBufferSize)324 Instance *Instance::Init(void *aBuffer, size_t *aBufferSize)
325 {
326     Instance *instance = nullptr;
327 
328     VerifyOrExit(aBufferSize != nullptr);
329 
330     // Make sure the input buffer is big enough
331     VerifyOrExit(sizeof(Instance) <= *aBufferSize, *aBufferSize = sizeof(Instance));
332 
333     VerifyOrExit(aBuffer != nullptr);
334 
335     instance = new (aBuffer) Instance();
336 
337     instance->AfterInit();
338 
339 exit:
340     return instance;
341 }
342 
343 #endif // OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
344 
Reset(void)345 void Instance::Reset(void) { otPlatReset(this); }
346 
347 #if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
ResetToBootloader(void)348 Error Instance::ResetToBootloader(void) { return otPlatResetToBootloader(this); }
349 #endif
350 
351 #if OPENTHREAD_RADIO
ResetRadioStack(void)352 void Instance::ResetRadioStack(void)
353 {
354     mRadio.Init();
355     mLinkRaw.Init();
356 }
357 #endif
358 
AfterInit(void)359 void Instance::AfterInit(void)
360 {
361     mIsInitialized = true;
362 #if OPENTHREAD_MTD || OPENTHREAD_FTD
363 
364     // Restore datasets and network information
365 
366     Get<Settings>().Init();
367     Get<Mle::MleRouter>().Restore();
368 
369 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
370     Get<Trel::Link>().AfterInit();
371 #endif
372 
373 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
374 
375 #if OPENTHREAD_ENABLE_VENDOR_EXTENSION
376     Get<Extension::ExtensionBase>().SignalInstanceInit();
377 #endif
378 }
379 
Finalize(void)380 void Instance::Finalize(void)
381 {
382     VerifyOrExit(mIsInitialized);
383 
384     mIsInitialized = false;
385 
386 #if OPENTHREAD_MTD || OPENTHREAD_FTD
387     IgnoreError(otThreadSetEnabled(this, false));
388     IgnoreError(otIp6SetEnabled(this, false));
389     IgnoreError(otLinkSetEnabled(this, false));
390 
391 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
392     Get<KeyManager>().DestroyTemporaryKeys();
393 #endif
394 
395     Get<Settings>().Deinit();
396 #endif
397 
398     IgnoreError(Get<Mac::SubMac>().Disable());
399 
400 #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
401 
402     /**
403      * Object was created on buffer, so instead of deleting
404      * the object we call destructor explicitly.
405      */
406     this->~Instance();
407 
408 #endif // !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
409 
410 exit:
411     return;
412 }
413 
414 #if OPENTHREAD_MTD || OPENTHREAD_FTD
415 
FactoryReset(void)416 void Instance::FactoryReset(void)
417 {
418     Get<Settings>().Wipe();
419 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
420     Get<KeyManager>().DestroyTemporaryKeys();
421     Get<KeyManager>().DestroyPersistentKeys();
422 #endif
423     otPlatReset(this);
424 }
425 
ErasePersistentInfo(void)426 Error Instance::ErasePersistentInfo(void)
427 {
428     Error error = kErrorNone;
429 
430     VerifyOrExit(Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
431     Get<Settings>().Wipe();
432 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
433     Get<KeyManager>().DestroyTemporaryKeys();
434     Get<KeyManager>().DestroyPersistentKeys();
435 #endif
436 
437 exit:
438     return error;
439 }
440 
GetBufferInfo(BufferInfo & aInfo)441 void Instance::GetBufferInfo(BufferInfo &aInfo)
442 {
443     aInfo.Clear();
444 
445     aInfo.mTotalBuffers   = Get<MessagePool>().GetTotalBufferCount();
446     aInfo.mFreeBuffers    = Get<MessagePool>().GetFreeBufferCount();
447     aInfo.mMaxUsedBuffers = Get<MessagePool>().GetMaxUsedBufferCount();
448 
449     Get<MeshForwarder>().GetSendQueue().GetInfo(aInfo.m6loSendQueue);
450     Get<MeshForwarder>().GetReassemblyQueue().GetInfo(aInfo.m6loReassemblyQueue);
451     Get<Ip6::Ip6>().GetSendQueue().GetInfo(aInfo.mIp6Queue);
452 
453 #if OPENTHREAD_FTD
454     Get<Ip6::Mpl>().GetBufferedMessageSet().GetInfo(aInfo.mMplQueue);
455 #endif
456 
457     Get<Mle::MleRouter>().GetMessageQueue().GetInfo(aInfo.mMleQueue);
458 
459     Get<Tmf::Agent>().GetRequestMessages().GetInfo(aInfo.mCoapQueue);
460     Get<Tmf::Agent>().GetCachedResponses().GetInfo(aInfo.mCoapQueue);
461 
462 #if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
463     Get<Tmf::SecureAgent>().GetRequestMessages().GetInfo(aInfo.mCoapSecureQueue);
464     Get<Tmf::SecureAgent>().GetCachedResponses().GetInfo(aInfo.mCoapSecureQueue);
465 #endif
466 
467 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
468     GetApplicationCoap().GetRequestMessages().GetInfo(aInfo.mApplicationCoapQueue);
469     GetApplicationCoap().GetCachedResponses().GetInfo(aInfo.mApplicationCoapQueue);
470 #endif
471 }
472 
ResetBufferInfo(void)473 void Instance::ResetBufferInfo(void) { Get<MessagePool>().ResetMaxUsedBufferCount(); }
474 
475 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
476 
477 #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
478 
SetLogLevel(LogLevel aLogLevel)479 void Instance::SetLogLevel(LogLevel aLogLevel)
480 {
481     if (aLogLevel != sLogLevel)
482     {
483         sLogLevel = aLogLevel;
484         otPlatLogHandleLevelChanged(sLogLevel);
485     }
486 }
487 
otPlatLogHandleLevelChanged(otLogLevel aLogLevel)488 extern "C" OT_TOOL_WEAK void otPlatLogHandleLevelChanged(otLogLevel aLogLevel) { OT_UNUSED_VARIABLE(aLogLevel); }
489 
490 #endif
491 
492 } // namespace ot
493