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