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 Thread API (FTD only).
32 */
33
34 #include "openthread-core-config.h"
35
36 #if OPENTHREAD_FTD
37
38 #include <openthread/thread_ftd.h>
39
40 #include "common/as_core_type.hpp"
41 #include "common/locator_getters.hpp"
42
43 using namespace ot;
44
otThreadGetMaxAllowedChildren(otInstance * aInstance)45 uint16_t otThreadGetMaxAllowedChildren(otInstance *aInstance)
46 {
47 return AsCoreType(aInstance).Get<ChildTable>().GetMaxChildrenAllowed();
48 }
49
otThreadSetMaxAllowedChildren(otInstance * aInstance,uint16_t aMaxChildren)50 otError otThreadSetMaxAllowedChildren(otInstance *aInstance, uint16_t aMaxChildren)
51 {
52 return AsCoreType(aInstance).Get<ChildTable>().SetMaxChildrenAllowed(aMaxChildren);
53 }
54
otThreadGetMaxChildIpAddresses(otInstance * aInstance)55 uint8_t otThreadGetMaxChildIpAddresses(otInstance *aInstance)
56 {
57 return AsCoreType(aInstance).Get<Mle::MleRouter>().GetMaxChildIpAddresses();
58 }
59
60 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
otThreadSetMaxChildIpAddresses(otInstance * aInstance,uint8_t aMaxIpAddresses)61 otError otThreadSetMaxChildIpAddresses(otInstance *aInstance, uint8_t aMaxIpAddresses)
62 {
63 return AsCoreType(aInstance).Get<Mle::MleRouter>().SetMaxChildIpAddresses(aMaxIpAddresses);
64 }
65 #endif
66
otThreadIsRouterEligible(otInstance * aInstance)67 bool otThreadIsRouterEligible(otInstance *aInstance)
68 {
69 return AsCoreType(aInstance).Get<Mle::MleRouter>().IsRouterEligible();
70 }
71
otThreadSetRouterEligible(otInstance * aInstance,bool aEligible)72 otError otThreadSetRouterEligible(otInstance *aInstance, bool aEligible)
73 {
74 return AsCoreType(aInstance).Get<Mle::MleRouter>().SetRouterEligible(aEligible);
75 }
76
otThreadSetPreferredRouterId(otInstance * aInstance,uint8_t aRouterId)77 otError otThreadSetPreferredRouterId(otInstance *aInstance, uint8_t aRouterId)
78 {
79 return AsCoreType(aInstance).Get<Mle::MleRouter>().SetPreferredRouterId(aRouterId);
80 }
81
82 #if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
otThreadGetDeviceProperties(otInstance * aInstance)83 const otDeviceProperties *otThreadGetDeviceProperties(otInstance *aInstance)
84 {
85 return &AsCoreType(aInstance).Get<Mle::MleRouter>().GetDeviceProperties();
86 }
87
otThreadSetDeviceProperties(otInstance * aInstance,const otDeviceProperties * aDeviceProperties)88 void otThreadSetDeviceProperties(otInstance *aInstance, const otDeviceProperties *aDeviceProperties)
89 {
90 AsCoreType(aInstance).Get<Mle::MleRouter>().SetDeviceProperties(AsCoreType(aDeviceProperties));
91 }
92 #endif
93
otThreadGetLocalLeaderWeight(otInstance * aInstance)94 uint8_t otThreadGetLocalLeaderWeight(otInstance *aInstance)
95 {
96 return AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderWeight();
97 }
98
otThreadSetLocalLeaderWeight(otInstance * aInstance,uint8_t aWeight)99 void otThreadSetLocalLeaderWeight(otInstance *aInstance, uint8_t aWeight)
100 {
101 AsCoreType(aInstance).Get<Mle::MleRouter>().SetLeaderWeight(aWeight);
102 }
103
104 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
otThreadGetPreferredLeaderPartitionId(otInstance * aInstance)105 uint32_t otThreadGetPreferredLeaderPartitionId(otInstance *aInstance)
106 {
107 return AsCoreType(aInstance).Get<Mle::MleRouter>().GetPreferredLeaderPartitionId();
108 }
109
otThreadSetPreferredLeaderPartitionId(otInstance * aInstance,uint32_t aPartitionId)110 void otThreadSetPreferredLeaderPartitionId(otInstance *aInstance, uint32_t aPartitionId)
111 {
112 AsCoreType(aInstance).Get<Mle::MleRouter>().SetPreferredLeaderPartitionId(aPartitionId);
113 }
114 #endif
115
otThreadGetJoinerUdpPort(otInstance * aInstance)116 uint16_t otThreadGetJoinerUdpPort(otInstance *aInstance)
117 {
118 return AsCoreType(aInstance).Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort();
119 }
120
otThreadSetJoinerUdpPort(otInstance * aInstance,uint16_t aJoinerUdpPort)121 otError otThreadSetJoinerUdpPort(otInstance *aInstance, uint16_t aJoinerUdpPort)
122 {
123 AsCoreType(aInstance).Get<MeshCoP::JoinerRouter>().SetJoinerUdpPort(aJoinerUdpPort);
124
125 return kErrorNone;
126 }
127
otThreadGetContextIdReuseDelay(otInstance * aInstance)128 uint32_t otThreadGetContextIdReuseDelay(otInstance *aInstance)
129 {
130 return AsCoreType(aInstance).Get<NetworkData::Leader>().GetContextIdReuseDelay();
131 }
132
otThreadSetContextIdReuseDelay(otInstance * aInstance,uint32_t aDelay)133 void otThreadSetContextIdReuseDelay(otInstance *aInstance, uint32_t aDelay)
134 {
135 AsCoreType(aInstance).Get<NetworkData::Leader>().SetContextIdReuseDelay(aDelay);
136 }
137
otThreadGetNetworkIdTimeout(otInstance * aInstance)138 uint8_t otThreadGetNetworkIdTimeout(otInstance *aInstance)
139 {
140 return AsCoreType(aInstance).Get<Mle::MleRouter>().GetNetworkIdTimeout();
141 }
142
otThreadSetNetworkIdTimeout(otInstance * aInstance,uint8_t aTimeout)143 void otThreadSetNetworkIdTimeout(otInstance *aInstance, uint8_t aTimeout)
144 {
145 AsCoreType(aInstance).Get<Mle::MleRouter>().SetNetworkIdTimeout(aTimeout);
146 }
147
otThreadGetRouterUpgradeThreshold(otInstance * aInstance)148 uint8_t otThreadGetRouterUpgradeThreshold(otInstance *aInstance)
149 {
150 return AsCoreType(aInstance).Get<Mle::MleRouter>().GetRouterUpgradeThreshold();
151 }
152
otThreadSetRouterUpgradeThreshold(otInstance * aInstance,uint8_t aThreshold)153 void otThreadSetRouterUpgradeThreshold(otInstance *aInstance, uint8_t aThreshold)
154 {
155 AsCoreType(aInstance).Get<Mle::MleRouter>().SetRouterUpgradeThreshold(aThreshold);
156 }
157
otThreadGetChildRouterLinks(otInstance * aInstance)158 uint8_t otThreadGetChildRouterLinks(otInstance *aInstance)
159 {
160 return AsCoreType(aInstance).Get<Mle::MleRouter>().GetChildRouterLinks();
161 }
162
otThreadSetChildRouterLinks(otInstance * aInstance,uint8_t aChildRouterLinks)163 otError otThreadSetChildRouterLinks(otInstance *aInstance, uint8_t aChildRouterLinks)
164 {
165 return AsCoreType(aInstance).Get<Mle::MleRouter>().SetChildRouterLinks(aChildRouterLinks);
166 }
167
otThreadReleaseRouterId(otInstance * aInstance,uint8_t aRouterId)168 otError otThreadReleaseRouterId(otInstance *aInstance, uint8_t aRouterId)
169 {
170 Error error = kErrorNone;
171
172 VerifyOrExit(aRouterId <= Mle::kMaxRouterId, error = kErrorInvalidArgs);
173
174 error = AsCoreType(aInstance).Get<RouterTable>().Release(aRouterId);
175
176 exit:
177 return error;
178 }
179
otThreadBecomeRouter(otInstance * aInstance)180 otError otThreadBecomeRouter(otInstance *aInstance)
181 {
182 Error error = kErrorInvalidState;
183
184 switch (AsCoreType(aInstance).Get<Mle::MleRouter>().GetRole())
185 {
186 case Mle::kRoleDisabled:
187 case Mle::kRoleDetached:
188 break;
189
190 case Mle::kRoleChild:
191 error = AsCoreType(aInstance).Get<Mle::MleRouter>().BecomeRouter(ThreadStatusTlv::kHaveChildIdRequest);
192 break;
193
194 case Mle::kRoleRouter:
195 case Mle::kRoleLeader:
196 error = kErrorNone;
197 break;
198 }
199
200 return error;
201 }
202
otThreadBecomeLeader(otInstance * aInstance)203 otError otThreadBecomeLeader(otInstance *aInstance)
204 {
205 return AsCoreType(aInstance).Get<Mle::MleRouter>().BecomeLeader();
206 }
207
otThreadGetRouterDowngradeThreshold(otInstance * aInstance)208 uint8_t otThreadGetRouterDowngradeThreshold(otInstance *aInstance)
209 {
210 return AsCoreType(aInstance).Get<Mle::MleRouter>().GetRouterDowngradeThreshold();
211 }
212
otThreadSetRouterDowngradeThreshold(otInstance * aInstance,uint8_t aThreshold)213 void otThreadSetRouterDowngradeThreshold(otInstance *aInstance, uint8_t aThreshold)
214 {
215 AsCoreType(aInstance).Get<Mle::MleRouter>().SetRouterDowngradeThreshold(aThreshold);
216 }
217
otThreadGetRouterSelectionJitter(otInstance * aInstance)218 uint8_t otThreadGetRouterSelectionJitter(otInstance *aInstance)
219 {
220 return AsCoreType(aInstance).Get<Mle::MleRouter>().GetRouterSelectionJitter();
221 }
222
otThreadSetRouterSelectionJitter(otInstance * aInstance,uint8_t aRouterJitter)223 void otThreadSetRouterSelectionJitter(otInstance *aInstance, uint8_t aRouterJitter)
224 {
225 AsCoreType(aInstance).Get<Mle::MleRouter>().SetRouterSelectionJitter(aRouterJitter);
226 }
227
otThreadGetChildInfoById(otInstance * aInstance,uint16_t aChildId,otChildInfo * aChildInfo)228 otError otThreadGetChildInfoById(otInstance *aInstance, uint16_t aChildId, otChildInfo *aChildInfo)
229 {
230 return AsCoreType(aInstance).Get<ChildTable>().GetChildInfoById(aChildId, AsCoreType(aChildInfo));
231 }
232
otThreadGetChildInfoByIndex(otInstance * aInstance,uint16_t aChildIndex,otChildInfo * aChildInfo)233 otError otThreadGetChildInfoByIndex(otInstance *aInstance, uint16_t aChildIndex, otChildInfo *aChildInfo)
234 {
235 return AsCoreType(aInstance).Get<ChildTable>().GetChildInfoByIndex(aChildIndex, AsCoreType(aChildInfo));
236 }
237
otThreadGetChildNextIp6Address(otInstance * aInstance,uint16_t aChildIndex,otChildIp6AddressIterator * aIterator,otIp6Address * aAddress)238 otError otThreadGetChildNextIp6Address(otInstance *aInstance,
239 uint16_t aChildIndex,
240 otChildIp6AddressIterator *aIterator,
241 otIp6Address *aAddress)
242 {
243 Error error = kErrorNone;
244 const Child *child;
245
246 AssertPointerIsNotNull(aIterator);
247 AssertPointerIsNotNull(aAddress);
248
249 child = AsCoreType(aInstance).Get<ChildTable>().GetChildAtIndex(aChildIndex);
250 VerifyOrExit(child != nullptr, error = kErrorInvalidArgs);
251 VerifyOrExit(child->IsStateValidOrRestoring(), error = kErrorInvalidArgs);
252
253 {
254 Child::AddressIterator iter(*child, *aIterator);
255
256 VerifyOrExit(!iter.IsDone(), error = kErrorNotFound);
257 *aAddress = *iter.GetAddress();
258
259 iter++;
260 *aIterator = iter.GetAsIndex();
261 }
262
263 exit:
264 return error;
265 }
266
otThreadGetRouterIdSequence(otInstance * aInstance)267 uint8_t otThreadGetRouterIdSequence(otInstance *aInstance)
268 {
269 return AsCoreType(aInstance).Get<RouterTable>().GetRouterIdSequence();
270 }
271
otThreadGetMaxRouterId(otInstance * aInstance)272 uint8_t otThreadGetMaxRouterId(otInstance *aInstance)
273 {
274 OT_UNUSED_VARIABLE(aInstance);
275 return Mle::kMaxRouterId;
276 }
277
otThreadGetRouterInfo(otInstance * aInstance,uint16_t aRouterId,otRouterInfo * aRouterInfo)278 otError otThreadGetRouterInfo(otInstance *aInstance, uint16_t aRouterId, otRouterInfo *aRouterInfo)
279 {
280 return AsCoreType(aInstance).Get<RouterTable>().GetRouterInfo(aRouterId, AsCoreType(aRouterInfo));
281 }
282
otThreadGetNextCacheEntry(otInstance * aInstance,otCacheEntryInfo * aEntryInfo,otCacheEntryIterator * aIterator)283 otError otThreadGetNextCacheEntry(otInstance *aInstance, otCacheEntryInfo *aEntryInfo, otCacheEntryIterator *aIterator)
284 {
285 return AsCoreType(aInstance).Get<AddressResolver>().GetNextCacheEntry(AsCoreType(aEntryInfo),
286 AsCoreType(aIterator));
287 }
288
289 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
otThreadSetSteeringData(otInstance * aInstance,const otExtAddress * aExtAddress)290 void otThreadSetSteeringData(otInstance *aInstance, const otExtAddress *aExtAddress)
291 {
292 AsCoreType(aInstance).Get<Mle::MleRouter>().SetSteeringData(AsCoreTypePtr(aExtAddress));
293 }
294 #endif
295
otThreadGetPskc(otInstance * aInstance,otPskc * aPskc)296 void otThreadGetPskc(otInstance *aInstance, otPskc *aPskc)
297 {
298 AsCoreType(aInstance).Get<KeyManager>().GetPskc(AsCoreType(aPskc));
299 }
300
301 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
otThreadGetPskcRef(otInstance * aInstance)302 otPskcRef otThreadGetPskcRef(otInstance *aInstance) { return AsCoreType(aInstance).Get<KeyManager>().GetPskcRef(); }
303 #endif
304
otThreadSetPskc(otInstance * aInstance,const otPskc * aPskc)305 otError otThreadSetPskc(otInstance *aInstance, const otPskc *aPskc)
306 {
307 Error error = kErrorNone;
308
309 VerifyOrExit(AsCoreType(aInstance).Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
310
311 AsCoreType(aInstance).Get<KeyManager>().SetPskc(AsCoreType(aPskc));
312 AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().Clear();
313 AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().Clear();
314
315 exit:
316 return error;
317 }
318
319 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
otThreadSetPskcRef(otInstance * aInstance,otPskcRef aKeyRef)320 otError otThreadSetPskcRef(otInstance *aInstance, otPskcRef aKeyRef)
321 {
322 Error error = kErrorNone;
323 Instance &instance = AsCoreType(aInstance);
324
325 VerifyOrExit(aKeyRef != 0, error = kErrorInvalidArgs);
326 VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
327
328 instance.Get<KeyManager>().SetPskcRef(aKeyRef);
329 instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
330 instance.Get<MeshCoP::PendingDatasetManager>().Clear();
331
332 exit:
333 return error;
334 }
335 #endif
336
otThreadGetParentPriority(otInstance * aInstance)337 int8_t otThreadGetParentPriority(otInstance *aInstance)
338 {
339 return AsCoreType(aInstance).Get<Mle::MleRouter>().GetAssignParentPriority();
340 }
341
otThreadSetParentPriority(otInstance * aInstance,int8_t aParentPriority)342 otError otThreadSetParentPriority(otInstance *aInstance, int8_t aParentPriority)
343 {
344 return AsCoreType(aInstance).Get<Mle::MleRouter>().SetAssignParentPriority(aParentPriority);
345 }
346
otThreadRegisterNeighborTableCallback(otInstance * aInstance,otNeighborTableCallback aCallback)347 void otThreadRegisterNeighborTableCallback(otInstance *aInstance, otNeighborTableCallback aCallback)
348 {
349 AsCoreType(aInstance).Get<NeighborTable>().RegisterCallback(aCallback);
350 }
351
otThreadSetDiscoveryRequestCallback(otInstance * aInstance,otThreadDiscoveryRequestCallback aCallback,void * aContext)352 void otThreadSetDiscoveryRequestCallback(otInstance *aInstance,
353 otThreadDiscoveryRequestCallback aCallback,
354 void *aContext)
355 {
356 AsCoreType(aInstance).Get<Mle::MleRouter>().SetDiscoveryRequestCallback(aCallback, aContext);
357 }
358
359 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
360
otThreadSendAddressNotification(otInstance * aInstance,otIp6Address * aDestination,otIp6Address * aTarget,otIp6InterfaceIdentifier * aMlIid)361 void otThreadSendAddressNotification(otInstance *aInstance,
362 otIp6Address *aDestination,
363 otIp6Address *aTarget,
364 otIp6InterfaceIdentifier *aMlIid)
365 {
366 AsCoreType(aInstance).Get<AddressResolver>().SendAddressQueryResponse(AsCoreType(aTarget), AsCoreType(aMlIid),
367 nullptr, AsCoreType(aDestination));
368 }
369
370 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
otThreadSendProactiveBackboneNotification(otInstance * aInstance,otIp6Address * aTarget,otIp6InterfaceIdentifier * aMlIid,uint32_t aTimeSinceLastTransaction)371 otError otThreadSendProactiveBackboneNotification(otInstance *aInstance,
372 otIp6Address *aTarget,
373 otIp6InterfaceIdentifier *aMlIid,
374 uint32_t aTimeSinceLastTransaction)
375 {
376 return AsCoreType(aInstance).Get<BackboneRouter::Manager>().SendProactiveBackboneNotification(
377 AsCoreType(aTarget), AsCoreType(aMlIid), aTimeSinceLastTransaction);
378 }
379 #endif
380
otThreadSetCcmEnabled(otInstance * aInstance,bool aEnabled)381 void otThreadSetCcmEnabled(otInstance *aInstance, bool aEnabled)
382 {
383 AsCoreType(aInstance).Get<Mle::MleRouter>().SetCcmEnabled(aEnabled);
384 }
385
otThreadSetThreadVersionCheckEnabled(otInstance * aInstance,bool aEnabled)386 void otThreadSetThreadVersionCheckEnabled(otInstance *aInstance, bool aEnabled)
387 {
388 AsCoreType(aInstance).Get<Mle::MleRouter>().SetThreadVersionCheckEnabled(aEnabled);
389 }
390
otThreadSetTmfOriginFilterEnabled(otInstance * aInstance,bool aEnabled)391 void otThreadSetTmfOriginFilterEnabled(otInstance *aInstance, bool aEnabled)
392 {
393 AsCoreType(aInstance).Get<Ip6::Ip6>().SetTmfOriginFilterEnabled(aEnabled);
394 }
395
otThreadIsTmfOriginFilterEnabled(otInstance * aInstance)396 bool otThreadIsTmfOriginFilterEnabled(otInstance *aInstance)
397 {
398 return AsCoreType(aInstance).Get<Ip6::Ip6>().IsTmfOriginFilterEnabled();
399 }
400
otThreadGetRouterIdRange(otInstance * aInstance,uint8_t * aMinRouterId,uint8_t * aMaxRouterId)401 void otThreadGetRouterIdRange(otInstance *aInstance, uint8_t *aMinRouterId, uint8_t *aMaxRouterId)
402 {
403 AssertPointerIsNotNull(aMinRouterId);
404 AssertPointerIsNotNull(aMaxRouterId);
405
406 AsCoreType(aInstance).Get<RouterTable>().GetRouterIdRange(*aMinRouterId, *aMaxRouterId);
407 }
408
otThreadSetRouterIdRange(otInstance * aInstance,uint8_t aMinRouterId,uint8_t aMaxRouterId)409 otError otThreadSetRouterIdRange(otInstance *aInstance, uint8_t aMinRouterId, uint8_t aMaxRouterId)
410 {
411 return AsCoreType(aInstance).Get<RouterTable>().SetRouterIdRange(aMinRouterId, aMaxRouterId);
412 }
413
otThreadGetAdvertisementTrickleIntervalMax(otInstance * aInstance)414 uint32_t otThreadGetAdvertisementTrickleIntervalMax(otInstance *aInstance)
415 {
416 return AsCoreType(aInstance).Get<Mle::MleRouter>().GetAdvertisementTrickleIntervalMax();
417 }
418
419 #endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
420
otThreadIsRouterIdAllocated(otInstance * aInstance,uint8_t aRouterId)421 bool otThreadIsRouterIdAllocated(otInstance *aInstance, uint8_t aRouterId)
422 {
423 return AsCoreType(aInstance).Get<RouterTable>().IsAllocated(aRouterId);
424 }
425
otThreadGetNextHopAndPathCost(otInstance * aInstance,uint16_t aDestRloc16,uint16_t * aNextHopRloc16,uint8_t * aPathCost)426 void otThreadGetNextHopAndPathCost(otInstance *aInstance,
427 uint16_t aDestRloc16,
428 uint16_t *aNextHopRloc16,
429 uint8_t *aPathCost)
430 {
431 uint8_t pathcost;
432 uint16_t nextHopRloc16;
433
434 AsCoreType(aInstance).Get<RouterTable>().GetNextHopAndPathCost(
435 aDestRloc16, (aNextHopRloc16 != nullptr) ? *aNextHopRloc16 : nextHopRloc16,
436 (aPathCost != nullptr) ? *aPathCost : pathcost);
437 }
438
439 #endif // OPENTHREAD_FTD
440