1 /*
2  *  Copyright (c) 2018, 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 #ifndef ROUTER_TABLE_HPP_
30 #define ROUTER_TABLE_HPP_
31 
32 #include "openthread-core-config.h"
33 
34 #if OPENTHREAD_FTD
35 
36 #include "common/array.hpp"
37 #include "common/const_cast.hpp"
38 #include "common/encoding.hpp"
39 #include "common/iterator_utils.hpp"
40 #include "common/locator.hpp"
41 #include "common/non_copyable.hpp"
42 #include "common/serial_number.hpp"
43 #include "common/tasklet.hpp"
44 #include "mac/mac_types.hpp"
45 #include "thread/mle_tlvs.hpp"
46 #include "thread/mle_types.hpp"
47 #include "thread/router.hpp"
48 #include "thread/thread_tlvs.hpp"
49 
50 namespace ot {
51 
52 class RouterTable : public InstanceLocator, private NonCopyable
53 {
54     friend class NeighborTable;
55 
56 public:
57     /**
58      * Constructor.
59      *
60      * @param[in]  aInstance  A reference to the OpenThread instance.
61      *
62      */
63     explicit RouterTable(Instance &aInstance);
64 
65     /**
66      * Clears the router table.
67      *
68      */
69     void Clear(void);
70 
71     /**
72      * Removes all neighbor links to routers.
73      *
74      */
75     void ClearNeighbors(void);
76 
77     /**
78      * Allocates a router with a random Router ID.
79      *
80      * @returns A pointer to the allocated router or `nullptr` if a Router ID is not available.
81      *
82      */
83     Router *Allocate(void);
84 
85     /**
86      * Allocates a router with a specified Router ID.
87      *
88      * @param[in] aRouterId   The Router ID to try to allocate.
89      *
90      * @returns A pointer to the allocated router or `nullptr` if the ID @p aRouterId could not be allocated.
91      *
92      */
93     Router *Allocate(uint8_t aRouterId);
94 
95     /**
96      * Releases a Router ID.
97      *
98      * @param[in]  aRouterId  The Router ID.
99      *
100      * @retval kErrorNone          Successfully released the Router ID @p aRouterId.
101      * @retval kErrorInvalidState  The device is not currently operating as a leader.
102      * @retval kErrorNotFound      The Router ID @p aRouterId is not currently allocated.
103      *
104      */
105     Error Release(uint8_t aRouterId);
106 
107     /**
108      * Removes a router link.
109      *
110      * @param[in]  aRouter  A reference to the router.
111      *
112      */
113     void RemoveRouterLink(Router &aRouter);
114 
115     /**
116      * Returns the number of active routers in the Thread network.
117      *
118      * @returns The number of active routers in the Thread network.
119      *
120      */
GetActiveRouterCount(void) const121     uint8_t GetActiveRouterCount(void) const { return mRouters.GetLength(); }
122 
123     /**
124      * Returns the leader in the Thread network.
125      *
126      * @returns A pointer to the Leader in the Thread network.
127      *
128      */
GetLeader(void)129     Router *GetLeader(void) { return AsNonConst(AsConst(this)->GetLeader()); }
130 
131     /**
132      * Returns the leader in the Thread network.
133      *
134      * @returns A pointer to the Leader in the Thread network.
135      *
136      */
137     const Router *GetLeader(void) const;
138 
139     /**
140      * Returns the leader's age in seconds, i.e., seconds since the last Router ID Sequence update.
141      *
142      * @returns The leader's age.
143      *
144      */
145     uint32_t GetLeaderAge(void) const;
146 
147     /**
148      * Returns the link cost for a neighboring router.
149      *
150      * @param[in]  aRouter   A router.
151      *
152      * @returns The link cost to @p aRouter.
153      *
154      */
155     uint8_t GetLinkCost(const Router &aRouter) const;
156 
157     /**
158      * Returns the link cost to the given Router.
159      *
160      * @param[in]  aRouterId  The Router ID.
161      *
162      * @returns The link cost to the Router.
163      *
164      */
165     uint8_t GetLinkCost(uint8_t aRouterId) const;
166 
167     /**
168      * Returns the minimum mesh path cost to the given RLOC16
169      *
170      * @param[in]  aDestRloc16  The RLOC16 of destination
171      *
172      * @returns The minimum mesh path cost to @p aDestRloc16 (via direct link or forwarding).
173      *
174      */
175     uint8_t GetPathCost(uint16_t aDestRloc16) const;
176 
177     /**
178      * Returns the mesh path cost to leader.
179      *
180      * @returns The path cost to leader.
181      *
182      */
183     uint8_t GetPathCostToLeader(void) const;
184 
185     /**
186      * Determines the next hop towards an RLOC16 destination.
187      *
188      * @param[in]  aDestRloc16  The RLOC16 of the destination.
189      *
190      * @returns A RLOC16 of the next hop if a route is known, `Mle::kInvalidRloc16` otherwise.
191      *
192      */
193     uint16_t GetNextHop(uint16_t aDestRloc16) const;
194 
195     /**
196      * Determines the next hop and the path cost towards an RLOC16 destination.
197      *
198      * @param[in]  aDestRloc16      The RLOC16 of the destination.
199      * @param[out] aNextHopRloc16   A reference to return the RLOC16 of next hop if known, or `Mle::kInvalidRloc16`.
200      * @param[out] aPathCost        A reference to return the path cost.
201      *
202      */
203     void GetNextHopAndPathCost(uint16_t aDestRloc16, uint16_t &aNextHopRloc16, uint8_t &aPathCost) const;
204 
205     /**
206      * Finds the router for a given Router ID.
207      *
208      * @param[in]  aRouterId  The Router ID to search for.
209      *
210      * @returns A pointer to the router or `nullptr` if the router could not be found.
211      *
212      */
FindRouterById(uint8_t aRouterId)213     Router *FindRouterById(uint8_t aRouterId) { return AsNonConst(AsConst(this)->FindRouterById(aRouterId)); }
214 
215     /**
216      * Finds the router for a given Router ID.
217      *
218      * @param[in]  aRouterId  The Router ID to search for.
219      *
220      * @returns A pointer to the router or `nullptr` if the router could not be found.
221      *
222      */
223     const Router *FindRouterById(uint8_t aRouterId) const;
224 
225     /**
226      * Finds the router for a given RLOC16.
227      *
228      * @param[in]  aRloc16  The RLOC16 to search for.
229      *
230      * @returns A pointer to the router or `nullptr` if the router could not be found.
231      *
232      */
FindRouterByRloc16(uint16_t aRloc16)233     Router *FindRouterByRloc16(uint16_t aRloc16) { return AsNonConst(AsConst(this)->FindRouterByRloc16(aRloc16)); }
234 
235     /**
236      * Finds the router for a given RLOC16.
237      *
238      * @param[in]  aRloc16  The RLOC16 to search for.
239      *
240      * @returns A pointer to the router or `nullptr` if the router could not be found.
241      *
242      */
243     const Router *FindRouterByRloc16(uint16_t aRloc16) const;
244 
245     /**
246      * Finds the router that is the next hop of a given router.
247      *
248      * @param[in]  aRouter  The router to find next hop of.
249      *
250      * @returns A pointer to the router or `nullptr` if the router could not be found.
251      *
252      */
FindNextHopOf(const Router & aRouter)253     Router *FindNextHopOf(const Router &aRouter) { return AsNonConst(AsConst(this)->FindNextHopOf(aRouter)); }
254 
255     /**
256      * Finds the router that is the next hop of a given router.
257      *
258      * @param[in]  aRouter  The router to find next hop of.
259      *
260      * @returns A pointer to the router or `nullptr` if the router could not be found.
261      *
262      */
263     const Router *FindNextHopOf(const Router &aRouter) const;
264 
265     /**
266      * Find the router for a given MAC Extended Address.
267      *
268      * @param[in]  aExtAddress  A reference to the MAC Extended Address.
269      *
270      * @returns A pointer to the router or `nullptr` if the router could not be found.
271      *
272      */
273     Router *FindRouter(const Mac::ExtAddress &aExtAddress);
274 
275     /**
276      * Indicates whether the router table contains a given `Neighbor` instance.
277      *
278      * @param[in]  aNeighbor  A reference to a `Neighbor`.
279      *
280      * @retval TRUE  if @p aNeighbor is a `Router` in the router table.
281      * @retval FALSE if @p aNeighbor is not a `Router` in the router table
282      *               (i.e. it can be the parent or parent candidate, or a `Child` of the child table).
283      *
284      */
Contains(const Neighbor & aNeighbor) const285     bool Contains(const Neighbor &aNeighbor) const
286     {
287         return mRouters.IsInArrayBuffer(&static_cast<const Router &>(aNeighbor));
288     }
289 
290     /**
291      * Retains diagnostic information for a given router.
292      *
293      * @param[in]   aRouterId    The router ID or RLOC16 for a given router.
294      * @param[out]  aRouterInfo  The router information.
295      *
296      * @retval kErrorNone          Successfully retrieved the router info for given id.
297      * @retval kErrorInvalidArgs   @p aRouterId is not a valid value for a router.
298      * @retval kErrorNotFound      No router entry with the given id.
299      *
300      */
301     Error GetRouterInfo(uint16_t aRouterId, Router::Info &aRouterInfo);
302 
303     /**
304      * Returns the Router ID Sequence.
305      *
306      * @returns The Router ID Sequence.
307      *
308      */
GetRouterIdSequence(void) const309     uint8_t GetRouterIdSequence(void) const { return mRouterIdSequence; }
310 
311     /**
312      * Returns the local time when the Router ID Sequence was last updated.
313      *
314      * @returns The local time when the Router ID Sequence was last updated.
315      *
316      */
GetRouterIdSequenceLastUpdated(void) const317     TimeMilli GetRouterIdSequenceLastUpdated(void) const { return mRouterIdSequenceLastUpdated; }
318 
319     /**
320      * Determines whether the Router ID Sequence in a received Route TLV is more recent than the current
321      * Router ID Sequence being used by `RouterTable`.
322      *
323      * @param[in] aRouteTlv   The Route TLV to compare.
324      *
325      * @retval TRUE    The Router ID Sequence in @p aRouteTlv is more recent.
326      * @retval FALSE   The Router ID Sequence in @p aRouteTlv is not more recent.
327      *
328      */
329     bool IsRouteTlvIdSequenceMoreRecent(const Mle::RouteTlv &aRouteTlv) const;
330 
331     /**
332      * Gets the number of router neighbors with `GetLinkQualityIn()` better than or equal to a given threshold.
333      *
334      * @param[in] aLinkQuality  Link quality threshold.
335      *
336      * @returns Number of router neighbors with link quality of @o aLinkQuality or better.
337      *
338      */
339     uint8_t GetNeighborCount(LinkQuality aLinkQuality) const;
340 
341     /**
342      * Indicates whether or not a Router ID is allocated.
343      *
344      * @param[in] aRouterId  The Router ID.
345      *
346      * @retval TRUE  if @p aRouterId is allocated.
347      * @retval FALSE if @p aRouterId is not allocated.
348      *
349      */
IsAllocated(uint8_t aRouterId) const350     bool IsAllocated(uint8_t aRouterId) const { return mRouterIdMap.IsAllocated(aRouterId); }
351 
352     /**
353      * Updates the Router ID allocation set.
354      *
355      * @param[in]  aRouterIdSequence  The Router ID Sequence.
356      * @param[in]  aRouterIdSet       The Router ID Set.
357      *
358      */
359     void UpdateRouterIdSet(uint8_t aRouterIdSequence, const Mle::RouterIdSet &aRouterIdSet);
360 
361     /**
362      * Updates the routes based on a received `RouteTlv` from a neighboring router.
363      *
364      * @param[in]  aRouteTlv    The received `RouteTlv`
365      * @param[in]  aNeighborId  The router ID of neighboring router from which @p aRouteTlv is received.
366      *
367      */
368     void UpdateRoutes(const Mle::RouteTlv &aRouteTlv, uint8_t aNeighborId);
369 
370     /**
371      * Updates the routes on an FED based on a received `RouteTlv` from the parent.
372      *
373      * MUST be called when device is an FED child and @p aRouteTlv is received from its current parent.
374      *
375      * @param[in]  aRouteTlv    The received `RouteTlv` from parent.
376      * @param[in]  aParentId    The Router ID of parent.
377      *
378      */
379     void UpdateRoutesOnFed(const Mle::RouteTlv &aRouteTlv, uint8_t aParentId);
380 
381     /**
382      * Gets the allocated Router ID set.
383      *
384      * @param[out]  aRouterIdSet   A reference to output the allocated Router ID set.
385      *
386      */
GetRouterIdSet(Mle::RouterIdSet & aRouterIdSet) const387     void GetRouterIdSet(Mle::RouterIdSet &aRouterIdSet) const { return mRouterIdMap.GetAsRouterIdSet(aRouterIdSet); }
388 
389     /**
390      * Fills a Route TLV.
391      *
392      * When @p aNeighbor is not `nullptr`, we limit the number of router entries to `kMaxRoutersInRouteTlvForLinkAccept`
393      * when populating `aRouteTlv`, so that the TLV can be appended in a Link Accept message. In this case, we ensure
394      * to include router entries associated with @p aNeighbor, leader, and this device itself.
395      *
396      * @param[out] aRouteTlv    A Route TLV to be filled.
397      * @param[in]  aNeighbor    A pointer to the receiver (in case TLV is for a Link Accept message).
398      *
399      */
400     void FillRouteTlv(Mle::RouteTlv &aRouteTlv, const Neighbor *aNeighbor = nullptr) const;
401 
402     /**
403      * Updates the router table and must be called with a one second period.
404      *
405      */
406     void HandleTimeTick(void);
407 
408 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
409     /**
410      * Gets the range of Router IDs.
411      *
412      * All the Router IDs in the range `[aMinRouterId, aMaxRouterId]` are allowed. This is intended for testing only.
413      *
414      * @param[out]  aMinRouterId   Reference to return the minimum Router ID.
415      * @param[out]  aMaxRouterId   Reference to return the maximum Router ID.
416      *
417      */
418     void GetRouterIdRange(uint8_t &aMinRouterId, uint8_t &aMaxRouterId) const;
419 
420     /**
421      * Sets the range of Router IDs.
422      *
423      * All the Router IDs in the range `[aMinRouterId, aMaxRouterId]` are allowed. This is intended for testing only.
424      *
425      * @param[in]  aMinRouterId   The minimum Router ID.
426      * @param[in]  aMaxRouterId   The maximum Router ID.
427      *
428      * @retval kErrorNone          Successfully set the Router ID range.
429      * @retval kErrorInvalidArgs   The given range is not valid.
430      *
431      */
432     Error SetRouterIdRange(uint8_t aMinRouterId, uint8_t aMaxRouterId);
433 #endif
434 
435     // The following methods are intended to support range-based `for`
436     // loop iteration over the router and should not be used
437     // directly.
438 
begin(void)439     Router       *begin(void) { return mRouters.begin(); }
end(void)440     Router       *end(void) { return mRouters.end(); }
begin(void) const441     const Router *begin(void) const { return mRouters.begin(); }
end(void) const442     const Router *end(void) const { return mRouters.end(); }
443 
444 private:
445     static constexpr uint32_t kRouterIdSequencePeriod     = 10; // in sec
446     static constexpr uint8_t  kLinkAcceptSequenceRollback = 64;
447 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
448     static constexpr uint8_t kMaxRoutersInRouteTlvForLinkAccept = 3;
449 #else
450     static constexpr uint8_t kMaxRoutersInRouteTlvForLinkAccept = 20;
451 #endif
452 
453     Router       *AddRouter(uint8_t aRouterId);
454     void          RemoveRouter(Router &aRouter);
455     Router       *FindNeighbor(uint16_t aRloc16);
456     Router       *FindNeighbor(const Mac::ExtAddress &aExtAddress);
457     Router       *FindNeighbor(const Mac::Address &aMacAddress);
458     const Router *FindRouter(const Router::AddressMatcher &aMatcher) const;
FindRouter(const Router::AddressMatcher & aMatcher)459     Router       *FindRouter(const Router::AddressMatcher &aMatcher)
460     {
461         return AsNonConst(AsConst(this)->FindRouter(aMatcher));
462     }
463 
464     void SignalTableChanged(void);
465     void HandleTableChanged(void);
466     void LogRouteTable(void) const;
467 
468     class RouterIdMap
469     {
470     public:
471         // The `RouterIdMap` tracks which Router IDs are allocated.
472         // For allocated IDs, tracks the index of the `Router` entry
473         // in `mRouters` array. For unallocated IDs, tracks the
474         // remaining reuse delay time (in seconds).
475 
RouterIdMap(void)476         RouterIdMap(void) { Clear(); }
Clear(void)477         void    Clear(void) { memset(mIndexes, 0, sizeof(mIndexes)); }
IsAllocated(uint8_t aRouterId) const478         bool    IsAllocated(uint8_t aRouterId) const { return (mIndexes[aRouterId] & kAllocatedFlag); }
GetIndex(uint8_t aRouterId) const479         uint8_t GetIndex(uint8_t aRouterId) const { return (mIndexes[aRouterId] & kIndexMask); }
SetIndex(uint8_t aRouterId,uint8_t aIndex)480         void    SetIndex(uint8_t aRouterId, uint8_t aIndex) { mIndexes[aRouterId] = kAllocatedFlag | aIndex; }
CanAllocate(uint8_t aRouterId) const481         bool    CanAllocate(uint8_t aRouterId) const { return (mIndexes[aRouterId] == 0); }
Release(uint8_t aRouterId)482         void    Release(uint8_t aRouterId) { mIndexes[aRouterId] = kReuseDelay; }
483         void    GetAsRouterIdSet(Mle::RouterIdSet &aRouterIdSet) const;
484         void    HandleTimeTick(void);
485 
486     private:
487         // The high bit in `mIndexes[aRouterId]` indicates whether or
488         // not the router ID is allocated. The lower 7 bits give either
489         // the index in `mRouter` array or remaining reuse delay time.
490 
491         static constexpr uint8_t kReuseDelay    = 100; // in sec
492         static constexpr uint8_t kAllocatedFlag = 1 << 7;
493         static constexpr uint8_t kIndexMask     = 0x7f;
494 
495         static_assert(kReuseDelay <= kIndexMask, "kReuseDelay does not fit in 7 bits");
496 
497         uint8_t mIndexes[Mle::kMaxRouterId + 1];
498     };
499 
500     using ChangedTask = TaskletIn<RouterTable, &RouterTable::HandleTableChanged>;
501 
502     Array<Router, Mle::kMaxRouters> mRouters;
503     ChangedTask                     mChangedTask;
504     RouterIdMap                     mRouterIdMap;
505     TimeMilli                       mRouterIdSequenceLastUpdated;
506     uint8_t                         mRouterIdSequence;
507 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
508     uint8_t mMinRouterId;
509     uint8_t mMaxRouterId;
510 #endif
511 };
512 
513 } // namespace ot
514 
515 #endif // OPENTHREAD_FTD
516 
517 #endif // ROUTER_TABLE_HPP_
518