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