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