1 /*
2 * Copyright (c) 2016, 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 Thread API (for both FTD and MTD).
32 */
33
34 #include "openthread-core-config.h"
35
36 #if OPENTHREAD_FTD || OPENTHREAD_MTD
37
38 #include <openthread/thread.h>
39
40 #include "common/debug.hpp"
41 #include "common/instance.hpp"
42 #include "common/locator_getters.hpp"
43 #include "common/settings.hpp"
44
45 using namespace ot;
46
otThreadGetChildTimeout(otInstance * aInstance)47 uint32_t otThreadGetChildTimeout(otInstance *aInstance)
48 {
49 Instance &instance = *static_cast<Instance *>(aInstance);
50
51 return instance.Get<Mle::MleRouter>().GetTimeout();
52 }
53
otThreadSetChildTimeout(otInstance * aInstance,uint32_t aTimeout)54 void otThreadSetChildTimeout(otInstance *aInstance, uint32_t aTimeout)
55 {
56 Instance &instance = *static_cast<Instance *>(aInstance);
57
58 instance.Get<Mle::MleRouter>().SetTimeout(aTimeout);
59 }
60
otThreadGetExtendedPanId(otInstance * aInstance)61 const otExtendedPanId *otThreadGetExtendedPanId(otInstance *aInstance)
62 {
63 Instance &instance = *static_cast<Instance *>(aInstance);
64
65 return &instance.Get<Mac::Mac>().GetExtendedPanId();
66 }
67
otThreadSetExtendedPanId(otInstance * aInstance,const otExtendedPanId * aExtendedPanId)68 otError otThreadSetExtendedPanId(otInstance *aInstance, const otExtendedPanId *aExtendedPanId)
69 {
70 Error error = kErrorNone;
71 Instance & instance = *static_cast<Instance *>(aInstance);
72 const Mac::ExtendedPanId &extPanId = *static_cast<const Mac::ExtendedPanId *>(aExtendedPanId);
73 Mle::MeshLocalPrefix prefix;
74
75 VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
76
77 instance.Get<Mac::Mac>().SetExtendedPanId(extPanId);
78
79 prefix.SetFromExtendedPanId(extPanId);
80 instance.Get<Mle::MleRouter>().SetMeshLocalPrefix(prefix);
81
82 instance.Get<MeshCoP::ActiveDataset>().Clear();
83 instance.Get<MeshCoP::PendingDataset>().Clear();
84
85 exit:
86 return error;
87 }
88
otThreadGetLeaderRloc(otInstance * aInstance,otIp6Address * aLeaderRloc)89 otError otThreadGetLeaderRloc(otInstance *aInstance, otIp6Address *aLeaderRloc)
90 {
91 Instance &instance = *static_cast<Instance *>(aInstance);
92
93 OT_ASSERT(aLeaderRloc != nullptr);
94
95 return instance.Get<Mle::MleRouter>().GetLeaderAddress(*static_cast<Ip6::Address *>(aLeaderRloc));
96 }
97
otThreadGetLinkMode(otInstance * aInstance)98 otLinkModeConfig otThreadGetLinkMode(otInstance *aInstance)
99 {
100 otLinkModeConfig config;
101 Instance & instance = *static_cast<Instance *>(aInstance);
102
103 instance.Get<Mle::MleRouter>().GetDeviceMode().Get(config);
104
105 return config;
106 }
107
otThreadSetLinkMode(otInstance * aInstance,otLinkModeConfig aConfig)108 otError otThreadSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig)
109 {
110 Instance &instance = *static_cast<Instance *>(aInstance);
111
112 return instance.Get<Mle::MleRouter>().SetDeviceMode(Mle::DeviceMode(aConfig));
113 }
114
otThreadGetNetworkKey(otInstance * aInstance)115 const otNetworkKey *otThreadGetNetworkKey(otInstance *aInstance)
116 {
117 Instance &instance = *static_cast<Instance *>(aInstance);
118
119 return &instance.Get<KeyManager>().GetNetworkKey();
120 }
121
otThreadSetNetworkKey(otInstance * aInstance,const otNetworkKey * aKey)122 otError otThreadSetNetworkKey(otInstance *aInstance, const otNetworkKey *aKey)
123 {
124 Error error = kErrorNone;
125 Instance &instance = *static_cast<Instance *>(aInstance);
126
127 OT_ASSERT(aKey != nullptr);
128
129 VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
130
131 error = instance.Get<KeyManager>().SetNetworkKey(*static_cast<const NetworkKey *>(aKey));
132 instance.Get<MeshCoP::ActiveDataset>().Clear();
133 instance.Get<MeshCoP::PendingDataset>().Clear();
134
135 exit:
136 return error;
137 }
138
otThreadGetRloc(otInstance * aInstance)139 const otIp6Address *otThreadGetRloc(otInstance *aInstance)
140 {
141 Instance &instance = *static_cast<Instance *>(aInstance);
142
143 return &instance.Get<Mle::MleRouter>().GetMeshLocal16();
144 }
145
otThreadGetMeshLocalEid(otInstance * aInstance)146 const otIp6Address *otThreadGetMeshLocalEid(otInstance *aInstance)
147 {
148 Instance &instance = *static_cast<Instance *>(aInstance);
149
150 return &instance.Get<Mle::MleRouter>().GetMeshLocal64();
151 }
152
otThreadGetMeshLocalPrefix(otInstance * aInstance)153 const otMeshLocalPrefix *otThreadGetMeshLocalPrefix(otInstance *aInstance)
154 {
155 Instance &instance = *static_cast<Instance *>(aInstance);
156
157 return &instance.Get<Mle::MleRouter>().GetMeshLocalPrefix();
158 }
159
otThreadSetMeshLocalPrefix(otInstance * aInstance,const otMeshLocalPrefix * aMeshLocalPrefix)160 otError otThreadSetMeshLocalPrefix(otInstance *aInstance, const otMeshLocalPrefix *aMeshLocalPrefix)
161 {
162 Error error = kErrorNone;
163 Instance &instance = *static_cast<Instance *>(aInstance);
164
165 VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
166
167 instance.Get<Mle::MleRouter>().SetMeshLocalPrefix(*static_cast<const Mle::MeshLocalPrefix *>(aMeshLocalPrefix));
168 instance.Get<MeshCoP::ActiveDataset>().Clear();
169 instance.Get<MeshCoP::PendingDataset>().Clear();
170
171 exit:
172 return error;
173 }
174
otThreadGetLinkLocalIp6Address(otInstance * aInstance)175 const otIp6Address *otThreadGetLinkLocalIp6Address(otInstance *aInstance)
176 {
177 Instance &instance = *static_cast<Instance *>(aInstance);
178
179 return &instance.Get<Mle::MleRouter>().GetLinkLocalAddress();
180 }
181
otThreadGetLinkLocalAllThreadNodesMulticastAddress(otInstance * aInstance)182 const otIp6Address *otThreadGetLinkLocalAllThreadNodesMulticastAddress(otInstance *aInstance)
183 {
184 Instance &instance = *static_cast<Instance *>(aInstance);
185
186 return &instance.Get<Mle::MleRouter>().GetLinkLocalAllThreadNodesAddress();
187 }
188
otThreadGetRealmLocalAllThreadNodesMulticastAddress(otInstance * aInstance)189 const otIp6Address *otThreadGetRealmLocalAllThreadNodesMulticastAddress(otInstance *aInstance)
190 {
191 Instance &instance = *static_cast<Instance *>(aInstance);
192
193 return &instance.Get<Mle::MleRouter>().GetRealmLocalAllThreadNodesAddress();
194 }
195
otThreadGetServiceAloc(otInstance * aInstance,uint8_t aServiceId,otIp6Address * aServiceAloc)196 otError otThreadGetServiceAloc(otInstance *aInstance, uint8_t aServiceId, otIp6Address *aServiceAloc)
197 {
198 Instance &instance = *static_cast<Instance *>(aInstance);
199
200 return instance.Get<Mle::MleRouter>().GetServiceAloc(aServiceId, *static_cast<Ip6::Address *>(aServiceAloc));
201 }
202
otThreadGetNetworkName(otInstance * aInstance)203 const char *otThreadGetNetworkName(otInstance *aInstance)
204 {
205 Instance &instance = *static_cast<Instance *>(aInstance);
206
207 return instance.Get<Mac::Mac>().GetNetworkName().GetAsCString();
208 }
209
otThreadSetNetworkName(otInstance * aInstance,const char * aNetworkName)210 otError otThreadSetNetworkName(otInstance *aInstance, const char *aNetworkName)
211 {
212 Error error = kErrorNone;
213 Instance &instance = *static_cast<Instance *>(aInstance);
214
215 VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
216
217 error = instance.Get<Mac::Mac>().SetNetworkName(aNetworkName);
218 instance.Get<MeshCoP::ActiveDataset>().Clear();
219 instance.Get<MeshCoP::PendingDataset>().Clear();
220
221 exit:
222 return error;
223 }
224
225 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
otThreadGetDomainName(otInstance * aInstance)226 const char *otThreadGetDomainName(otInstance *aInstance)
227 {
228 Instance &instance = *static_cast<Instance *>(aInstance);
229
230 return instance.Get<Mac::Mac>().GetDomainName().GetAsCString();
231 }
232
otThreadSetDomainName(otInstance * aInstance,const char * aDomainName)233 otError otThreadSetDomainName(otInstance *aInstance, const char *aDomainName)
234 {
235 Error error = kErrorNone;
236 Instance &instance = *static_cast<Instance *>(aInstance);
237
238 VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
239
240 error = instance.Get<Mac::Mac>().SetDomainName(aDomainName);
241
242 exit:
243 return error;
244 }
245
246 #if OPENTHREAD_CONFIG_DUA_ENABLE
otThreadSetFixedDuaInterfaceIdentifier(otInstance * aInstance,const otIp6InterfaceIdentifier * aIid)247 otError otThreadSetFixedDuaInterfaceIdentifier(otInstance *aInstance, const otIp6InterfaceIdentifier *aIid)
248 {
249 Instance &instance = *static_cast<Instance *>(aInstance);
250 Error error = kErrorNone;
251
252 if (aIid)
253 {
254 error = instance.Get<DuaManager>().SetFixedDuaInterfaceIdentifier(
255 *static_cast<const Ip6::InterfaceIdentifier *>(aIid));
256 }
257 else
258 {
259 instance.Get<DuaManager>().ClearFixedDuaInterfaceIdentifier();
260 }
261
262 return error;
263 }
264
otThreadGetFixedDuaInterfaceIdentifier(otInstance * aInstance)265 const otIp6InterfaceIdentifier *otThreadGetFixedDuaInterfaceIdentifier(otInstance *aInstance)
266 {
267 Instance & instance = *static_cast<Instance *>(aInstance);
268 const otIp6InterfaceIdentifier *iid = nullptr;
269
270 if (instance.Get<DuaManager>().IsFixedDuaInterfaceIdentifierSet())
271 {
272 iid = &instance.Get<DuaManager>().GetFixedDuaInterfaceIdentifier();
273 }
274
275 return iid;
276 }
277 #endif // OPENTHREAD_CONFIG_DUA_ENABLE
278
279 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
280
otThreadGetKeySequenceCounter(otInstance * aInstance)281 uint32_t otThreadGetKeySequenceCounter(otInstance *aInstance)
282 {
283 Instance &instance = *static_cast<Instance *>(aInstance);
284
285 return instance.Get<KeyManager>().GetCurrentKeySequence();
286 }
287
otThreadSetKeySequenceCounter(otInstance * aInstance,uint32_t aKeySequenceCounter)288 void otThreadSetKeySequenceCounter(otInstance *aInstance, uint32_t aKeySequenceCounter)
289 {
290 Instance &instance = *static_cast<Instance *>(aInstance);
291
292 instance.Get<KeyManager>().SetCurrentKeySequence(aKeySequenceCounter);
293 }
294
otThreadGetKeySwitchGuardTime(otInstance * aInstance)295 uint32_t otThreadGetKeySwitchGuardTime(otInstance *aInstance)
296 {
297 Instance &instance = *static_cast<Instance *>(aInstance);
298
299 return instance.Get<KeyManager>().GetKeySwitchGuardTime();
300 }
301
otThreadSetKeySwitchGuardTime(otInstance * aInstance,uint32_t aKeySwitchGuardTime)302 void otThreadSetKeySwitchGuardTime(otInstance *aInstance, uint32_t aKeySwitchGuardTime)
303 {
304 Instance &instance = *static_cast<Instance *>(aInstance);
305
306 instance.Get<KeyManager>().SetKeySwitchGuardTime(aKeySwitchGuardTime);
307 }
308
otThreadBecomeDetached(otInstance * aInstance)309 otError otThreadBecomeDetached(otInstance *aInstance)
310 {
311 Instance &instance = *static_cast<Instance *>(aInstance);
312
313 return instance.Get<Mle::MleRouter>().BecomeDetached();
314 }
315
otThreadBecomeChild(otInstance * aInstance)316 otError otThreadBecomeChild(otInstance *aInstance)
317 {
318 Instance &instance = *static_cast<Instance *>(aInstance);
319
320 return instance.Get<Mle::MleRouter>().BecomeChild(Mle::kAttachAny);
321 }
322
otThreadGetNextNeighborInfo(otInstance * aInstance,otNeighborInfoIterator * aIterator,otNeighborInfo * aInfo)323 otError otThreadGetNextNeighborInfo(otInstance *aInstance, otNeighborInfoIterator *aIterator, otNeighborInfo *aInfo)
324 {
325 Instance &instance = *static_cast<Instance *>(aInstance);
326
327 OT_ASSERT((aInfo != nullptr) && (aIterator != nullptr));
328
329 return instance.Get<NeighborTable>().GetNextNeighborInfo(*aIterator, *static_cast<Neighbor::Info *>(aInfo));
330 }
331
otThreadGetDeviceRole(otInstance * aInstance)332 otDeviceRole otThreadGetDeviceRole(otInstance *aInstance)
333 {
334 Instance &instance = *static_cast<Instance *>(aInstance);
335
336 return static_cast<otDeviceRole>(instance.Get<Mle::MleRouter>().GetRole());
337 }
338
otThreadDeviceRoleToString(otDeviceRole aRole)339 const char *otThreadDeviceRoleToString(otDeviceRole aRole)
340 {
341 return Mle::Mle::RoleToString(static_cast<Mle::DeviceRole>(aRole));
342 }
343
otThreadGetLeaderData(otInstance * aInstance,otLeaderData * aLeaderData)344 otError otThreadGetLeaderData(otInstance *aInstance, otLeaderData *aLeaderData)
345 {
346 Instance &instance = *static_cast<Instance *>(aInstance);
347 Error error = kErrorNone;
348
349 OT_ASSERT(aLeaderData != nullptr);
350
351 VerifyOrExit(instance.Get<Mle::MleRouter>().IsAttached(), error = kErrorDetached);
352 *aLeaderData = instance.Get<Mle::MleRouter>().GetLeaderData();
353
354 exit:
355 return error;
356 }
357
otThreadGetLeaderRouterId(otInstance * aInstance)358 uint8_t otThreadGetLeaderRouterId(otInstance *aInstance)
359 {
360 Instance &instance = *static_cast<Instance *>(aInstance);
361
362 return instance.Get<Mle::MleRouter>().GetLeaderId();
363 }
364
otThreadGetLeaderWeight(otInstance * aInstance)365 uint8_t otThreadGetLeaderWeight(otInstance *aInstance)
366 {
367 Instance &instance = *static_cast<Instance *>(aInstance);
368
369 return instance.Get<Mle::MleRouter>().GetLeaderData().GetWeighting();
370 }
371
otThreadGetPartitionId(otInstance * aInstance)372 uint32_t otThreadGetPartitionId(otInstance *aInstance)
373 {
374 Instance &instance = *static_cast<Instance *>(aInstance);
375
376 return instance.Get<Mle::MleRouter>().GetLeaderData().GetPartitionId();
377 }
378
otThreadGetRloc16(otInstance * aInstance)379 uint16_t otThreadGetRloc16(otInstance *aInstance)
380 {
381 Instance &instance = *static_cast<Instance *>(aInstance);
382
383 return instance.Get<Mle::MleRouter>().GetRloc16();
384 }
385
otThreadGetParentInfo(otInstance * aInstance,otRouterInfo * aParentInfo)386 otError otThreadGetParentInfo(otInstance *aInstance, otRouterInfo *aParentInfo)
387 {
388 Instance &instance = *static_cast<Instance *>(aInstance);
389 Error error = kErrorNone;
390 Router * parent;
391
392 OT_ASSERT(aParentInfo != nullptr);
393
394 // Reference device needs get the original parent's info even after the node state changed.
395 #if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
396 VerifyOrExit(instance.Get<Mle::MleRouter>().IsChild(), error = kErrorInvalidState);
397 #endif
398
399 parent = &instance.Get<Mle::MleRouter>().GetParent();
400
401 aParentInfo->mExtAddress = parent->GetExtAddress();
402 aParentInfo->mRloc16 = parent->GetRloc16();
403 aParentInfo->mRouterId = Mle::Mle::RouterIdFromRloc16(parent->GetRloc16());
404 aParentInfo->mNextHop = parent->GetNextHop();
405 aParentInfo->mPathCost = parent->GetCost();
406 aParentInfo->mLinkQualityIn = parent->GetLinkInfo().GetLinkQuality();
407 aParentInfo->mLinkQualityOut = parent->GetLinkQualityOut();
408 aParentInfo->mAge = static_cast<uint8_t>(Time::MsecToSec(TimerMilli::GetNow() - parent->GetLastHeard()));
409 aParentInfo->mAllocated = true;
410 aParentInfo->mLinkEstablished = parent->IsStateValid();
411
412 #if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
413 exit:
414 #endif
415 return error;
416 }
417
otThreadGetParentAverageRssi(otInstance * aInstance,int8_t * aParentRssi)418 otError otThreadGetParentAverageRssi(otInstance *aInstance, int8_t *aParentRssi)
419 {
420 Error error = kErrorNone;
421 Instance &instance = *static_cast<Instance *>(aInstance);
422
423 OT_ASSERT(aParentRssi != nullptr);
424
425 *aParentRssi = instance.Get<Mle::MleRouter>().GetParent().GetLinkInfo().GetAverageRss();
426
427 VerifyOrExit(*aParentRssi != OT_RADIO_RSSI_INVALID, error = kErrorFailed);
428
429 exit:
430 return error;
431 }
432
otThreadGetParentLastRssi(otInstance * aInstance,int8_t * aLastRssi)433 otError otThreadGetParentLastRssi(otInstance *aInstance, int8_t *aLastRssi)
434 {
435 Error error = kErrorNone;
436 Instance &instance = *static_cast<Instance *>(aInstance);
437
438 OT_ASSERT(aLastRssi != nullptr);
439
440 *aLastRssi = instance.Get<Mle::MleRouter>().GetParent().GetLinkInfo().GetLastRss();
441
442 VerifyOrExit(*aLastRssi != OT_RADIO_RSSI_INVALID, error = kErrorFailed);
443
444 exit:
445 return error;
446 }
447
otThreadSetEnabled(otInstance * aInstance,bool aEnabled)448 otError otThreadSetEnabled(otInstance *aInstance, bool aEnabled)
449 {
450 Error error = kErrorNone;
451 Instance &instance = *static_cast<Instance *>(aInstance);
452
453 if (aEnabled)
454 {
455 error = instance.Get<Mle::MleRouter>().Start(/* aAnnounceAttach */ false);
456 }
457 else
458 {
459 instance.Get<Mle::MleRouter>().Stop(true);
460 }
461
462 return error;
463 }
464
otThreadGetVersion(void)465 uint16_t otThreadGetVersion(void)
466 {
467 return OPENTHREAD_CONFIG_THREAD_VERSION;
468 }
469
otThreadIsSingleton(otInstance * aInstance)470 bool otThreadIsSingleton(otInstance *aInstance)
471 {
472 Instance &instance = *static_cast<Instance *>(aInstance);
473
474 return instance.Get<Mle::MleRouter>().IsSingleton();
475 }
476
otThreadDiscover(otInstance * aInstance,uint32_t aScanChannels,uint16_t aPanId,bool aJoiner,bool aEnableEui64Filtering,otHandleActiveScanResult aCallback,void * aCallbackContext)477 otError otThreadDiscover(otInstance * aInstance,
478 uint32_t aScanChannels,
479 uint16_t aPanId,
480 bool aJoiner,
481 bool aEnableEui64Filtering,
482 otHandleActiveScanResult aCallback,
483 void * aCallbackContext)
484 {
485 Instance &instance = *static_cast<Instance *>(aInstance);
486
487 return instance.Get<Mle::DiscoverScanner>().Discover(
488 static_cast<Mac::ChannelMask>(aScanChannels), aPanId, aJoiner, aEnableEui64Filtering,
489 /* aFilterIndexes (use hash of factory EUI64) */ nullptr, aCallback, aCallbackContext);
490 }
491
otThreadSetJoinerAdvertisement(otInstance * aInstance,uint32_t aOui,const uint8_t * aAdvData,uint8_t aAdvDataLength)492 otError otThreadSetJoinerAdvertisement(otInstance * aInstance,
493 uint32_t aOui,
494 const uint8_t *aAdvData,
495 uint8_t aAdvDataLength)
496 {
497 Instance &instance = *static_cast<Instance *>(aInstance);
498
499 return instance.Get<Mle::DiscoverScanner>().SetJoinerAdvertisement(aOui, aAdvData, aAdvDataLength);
500 }
501
otThreadIsDiscoverInProgress(otInstance * aInstance)502 bool otThreadIsDiscoverInProgress(otInstance *aInstance)
503 {
504 Instance &instance = *static_cast<Instance *>(aInstance);
505
506 return instance.Get<Mle::DiscoverScanner>().IsInProgress();
507 }
508
otThreadGetIp6Counters(otInstance * aInstance)509 const otIpCounters *otThreadGetIp6Counters(otInstance *aInstance)
510 {
511 Instance &instance = *static_cast<Instance *>(aInstance);
512
513 return &instance.Get<MeshForwarder>().GetCounters();
514 }
515
otThreadResetIp6Counters(otInstance * aInstance)516 void otThreadResetIp6Counters(otInstance *aInstance)
517 {
518 Instance &instance = *static_cast<Instance *>(aInstance);
519
520 instance.Get<MeshForwarder>().ResetCounters();
521 }
522
otThreadGetMleCounters(otInstance * aInstance)523 const otMleCounters *otThreadGetMleCounters(otInstance *aInstance)
524 {
525 Instance &instance = *static_cast<Instance *>(aInstance);
526
527 return &instance.Get<Mle::MleRouter>().GetCounters();
528 }
529
otThreadResetMleCounters(otInstance * aInstance)530 void otThreadResetMleCounters(otInstance *aInstance)
531 {
532 Instance &instance = *static_cast<Instance *>(aInstance);
533
534 instance.Get<Mle::MleRouter>().ResetCounters();
535 }
536
otThreadRegisterParentResponseCallback(otInstance * aInstance,otThreadParentResponseCallback aCallback,void * aContext)537 void otThreadRegisterParentResponseCallback(otInstance * aInstance,
538 otThreadParentResponseCallback aCallback,
539 void * aContext)
540 {
541 Instance &instance = *static_cast<Instance *>(aInstance);
542
543 instance.Get<Mle::MleRouter>().RegisterParentResponseStatsCallback(aCallback, aContext);
544 }
545
546 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
547