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