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