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 #include "router_table.hpp"
30 
31 #if OPENTHREAD_FTD
32 
33 #include "common/code_utils.hpp"
34 #include "common/instance.hpp"
35 #include "common/locator_getters.hpp"
36 #include "common/logging.hpp"
37 #include "common/timer.hpp"
38 #include "thread/mle.hpp"
39 #include "thread/mle_router.hpp"
40 #include "thread/network_data_leader.hpp"
41 #include "thread/thread_netif.hpp"
42 
43 namespace ot {
44 
Iterator(Instance & aInstance)45 RouterTable::Iterator::Iterator(Instance &aInstance)
46     : InstanceLocator(aInstance)
47     , ItemPtrIterator(Get<RouterTable>().GetFirstEntry())
48 {
49 }
50 
Advance(void)51 void RouterTable::Iterator::Advance(void)
52 {
53     mItem = Get<RouterTable>().GetNextEntry(mItem);
54 }
55 
RouterTable(Instance & aInstance)56 RouterTable::RouterTable(Instance &aInstance)
57     : InstanceLocator(aInstance)
58     , mRouterIdSequenceLastUpdated(0)
59     , mRouterIdSequence(Random::NonCrypto::GetUint8())
60     , mActiveRouterCount(0)
61 {
62     for (Router &router : mRouters)
63     {
64         router.Init(aInstance);
65     }
66 
67     Clear();
68 }
69 
GetFirstEntry(void) const70 const Router *RouterTable::GetFirstEntry(void) const
71 {
72     const Router *router = &mRouters[0];
73     VerifyOrExit(router->GetRloc16() != 0xffff, router = nullptr);
74 
75 exit:
76     return router;
77 }
78 
GetNextEntry(const Router * aRouter) const79 const Router *RouterTable::GetNextEntry(const Router *aRouter) const
80 {
81     VerifyOrExit(aRouter != nullptr);
82     aRouter++;
83     VerifyOrExit(aRouter < &mRouters[Mle::kMaxRouters], aRouter = nullptr);
84     VerifyOrExit(aRouter->GetRloc16() != 0xffff, aRouter = nullptr);
85 
86 exit:
87     return aRouter;
88 }
89 
Clear(void)90 void RouterTable::Clear(void)
91 {
92     ClearNeighbors();
93     mAllocatedRouterIds.Clear();
94     memset(mRouterIdReuseDelay, 0, sizeof(mRouterIdReuseDelay));
95     UpdateAllocation();
96 }
97 
ClearNeighbors(void)98 void RouterTable::ClearNeighbors(void)
99 {
100     for (Router &router : mRouters)
101     {
102         if (router.IsStateValid())
103         {
104             Get<NeighborTable>().Signal(NeighborTable::kRouterRemoved, router);
105         }
106 
107         router.SetState(Neighbor::kStateInvalid);
108     }
109 }
110 
IsAllocated(uint8_t aRouterId) const111 bool RouterTable::IsAllocated(uint8_t aRouterId) const
112 {
113     return mAllocatedRouterIds.Contains(aRouterId);
114 }
115 
UpdateAllocation(void)116 void RouterTable::UpdateAllocation(void)
117 {
118     uint8_t indexMap[Mle::kMaxRouterId + 1];
119 
120     mActiveRouterCount = 0;
121 
122     // build index map
123     for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
124     {
125         if (IsAllocated(routerId) && mActiveRouterCount < Mle::kMaxRouters)
126         {
127             indexMap[routerId] = mActiveRouterCount++;
128         }
129         else
130         {
131             indexMap[routerId] = Mle::kInvalidRouterId;
132         }
133     }
134 
135     // shift entries forward
136     for (int index = Mle::kMaxRouters - 2; index >= 0; index--)
137     {
138         uint8_t routerId = mRouters[index].GetRouterId();
139         uint8_t newIndex;
140 
141         if (routerId > Mle::kMaxRouterId || indexMap[routerId] == Mle::kInvalidRouterId)
142         {
143             continue;
144         }
145 
146         newIndex = indexMap[routerId];
147 
148         if (newIndex > index)
149         {
150             mRouters[newIndex] = mRouters[index];
151         }
152     }
153 
154     // shift entries backward
155     for (uint8_t index = 1; index < Mle::kMaxRouters; index++)
156     {
157         uint8_t routerId = mRouters[index].GetRouterId();
158         uint8_t newIndex;
159 
160         if (routerId > Mle::kMaxRouterId || indexMap[routerId] == Mle::kInvalidRouterId)
161         {
162             continue;
163         }
164 
165         newIndex = indexMap[routerId];
166 
167         if (newIndex < index)
168         {
169             mRouters[newIndex] = mRouters[index];
170         }
171     }
172 
173     // fix replaced entries
174     for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
175     {
176         uint8_t index = indexMap[routerId];
177 
178         if (index != Mle::kInvalidRouterId)
179         {
180             Router &router = mRouters[index];
181 
182             if (router.GetRouterId() != routerId)
183             {
184                 router.Clear();
185                 router.SetRloc16(Mle::Mle::Rloc16FromRouterId(routerId));
186                 router.SetNextHop(Mle::kInvalidRouterId);
187             }
188         }
189     }
190 
191     // clear unused entries
192     for (uint8_t index = mActiveRouterCount; index < Mle::kMaxRouters; index++)
193     {
194         Router &router = mRouters[index];
195         router.Clear();
196         router.SetRloc16(0xffff);
197     }
198 }
199 
Allocate(void)200 Router *RouterTable::Allocate(void)
201 {
202     Router *rval         = nullptr;
203     uint8_t numAvailable = 0;
204     uint8_t freeBit;
205 
206     // count available router ids
207     for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
208     {
209         if (!IsAllocated(routerId) && mRouterIdReuseDelay[routerId] == 0)
210         {
211             numAvailable++;
212         }
213     }
214 
215     VerifyOrExit(mActiveRouterCount < Mle::kMaxRouters && numAvailable > 0);
216 
217     // choose available router id at random
218     freeBit = Random::NonCrypto::GetUint8InRange(0, numAvailable);
219 
220     // allocate router
221     for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
222     {
223         if (IsAllocated(routerId) || mRouterIdReuseDelay[routerId] > 0)
224         {
225             continue;
226         }
227 
228         if (freeBit == 0)
229         {
230             rval = Allocate(routerId);
231             OT_ASSERT(rval != nullptr);
232             ExitNow();
233         }
234 
235         freeBit--;
236     }
237 
238 exit:
239     return rval;
240 }
241 
Allocate(uint8_t aRouterId)242 Router *RouterTable::Allocate(uint8_t aRouterId)
243 {
244     Router *rval = nullptr;
245 
246     VerifyOrExit(aRouterId <= Mle::kMaxRouterId && mActiveRouterCount < Mle::kMaxRouters && !IsAllocated(aRouterId) &&
247                  mRouterIdReuseDelay[aRouterId] == 0);
248 
249     mAllocatedRouterIds.Add(aRouterId);
250     UpdateAllocation();
251 
252     rval = GetRouter(aRouterId);
253     rval->SetLastHeard(TimerMilli::GetNow());
254 
255     mRouterIdSequence++;
256     mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
257     Get<Mle::MleRouter>().ResetAdvertiseInterval();
258 
259     otLogNoteMle("Allocate router id %d", aRouterId);
260 
261 exit:
262     return rval;
263 }
264 
Release(uint8_t aRouterId)265 Error RouterTable::Release(uint8_t aRouterId)
266 {
267     Error    error  = kErrorNone;
268     uint16_t rloc16 = Mle::Mle::Rloc16FromRouterId(aRouterId);
269     Router * router;
270 
271     OT_ASSERT(aRouterId <= Mle::kMaxRouterId);
272 
273     VerifyOrExit(Get<Mle::MleRouter>().IsLeader(), error = kErrorInvalidState);
274     VerifyOrExit(IsAllocated(aRouterId), error = kErrorNotFound);
275 
276     router = GetNeighbor(rloc16);
277 
278     if (router != nullptr)
279     {
280         Get<NeighborTable>().Signal(NeighborTable::kRouterRemoved, *router);
281     }
282 
283     mAllocatedRouterIds.Remove(aRouterId);
284     UpdateAllocation();
285 
286     mRouterIdReuseDelay[aRouterId] = Mle::kRouterIdReuseDelay;
287 
288     for (router = GetFirstEntry(); router != nullptr; router = GetNextEntry(router))
289     {
290         if (router->GetNextHop() == rloc16)
291         {
292             router->SetNextHop(Mle::kInvalidRouterId);
293             router->SetCost(0);
294         }
295     }
296 
297     mRouterIdSequence++;
298     mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
299 
300     Get<AddressResolver>().Remove(aRouterId);
301     Get<NetworkData::Leader>().RemoveBorderRouter(rloc16, NetworkData::Leader::kMatchModeRouterId);
302     Get<Mle::MleRouter>().ResetAdvertiseInterval();
303 
304     otLogNoteMle("Release router id %d", aRouterId);
305 
306 exit:
307     return error;
308 }
309 
RemoveRouterLink(Router & aRouter)310 void RouterTable::RemoveRouterLink(Router &aRouter)
311 {
312     aRouter.SetLinkQualityOut(0);
313     aRouter.SetLastHeard(TimerMilli::GetNow());
314 
315     for (Router *cur = GetFirstEntry(); cur != nullptr; cur = GetNextEntry(cur))
316     {
317         if (cur->GetNextHop() == aRouter.GetRouterId())
318         {
319             cur->SetNextHop(Mle::kInvalidRouterId);
320             cur->SetCost(0);
321 
322             if (GetLinkCost(*cur) >= Mle::kMaxRouteCost)
323             {
324                 Get<Mle::MleRouter>().ResetAdvertiseInterval();
325             }
326         }
327     }
328 
329     if (aRouter.GetNextHop() == Mle::kInvalidRouterId)
330     {
331         Get<Mle::MleRouter>().ResetAdvertiseInterval();
332 
333         // Clear all EID-to-RLOC entries associated with the router.
334         Get<AddressResolver>().Remove(aRouter.GetRouterId());
335     }
336 }
337 
GetActiveLinkCount(void) const338 uint8_t RouterTable::GetActiveLinkCount(void) const
339 {
340     uint8_t activeLinks = 0;
341 
342     for (const Router *router = GetFirstEntry(); router != nullptr; router = GetNextEntry(router))
343     {
344         if (router->IsStateValid())
345         {
346             activeLinks++;
347         }
348     }
349 
350     return activeLinks;
351 }
352 
FindRouter(const Router::AddressMatcher & aMatcher) const353 const Router *RouterTable::FindRouter(const Router::AddressMatcher &aMatcher) const
354 {
355     const Router *router;
356 
357     for (router = GetFirstEntry(); router != nullptr; router = GetNextEntry(router))
358     {
359         if (router->Matches(aMatcher))
360         {
361             break;
362         }
363     }
364 
365     return router;
366 }
367 
GetNeighbor(uint16_t aRloc16)368 Router *RouterTable::GetNeighbor(uint16_t aRloc16)
369 {
370     Router *router = nullptr;
371 
372     VerifyOrExit(aRloc16 != Get<Mle::MleRouter>().GetRloc16());
373     router = FindRouter(Router::AddressMatcher(aRloc16, Router::kInStateValid));
374 
375 exit:
376     return router;
377 }
378 
GetNeighbor(const Mac::ExtAddress & aExtAddress)379 Router *RouterTable::GetNeighbor(const Mac::ExtAddress &aExtAddress)
380 {
381     return FindRouter(Router::AddressMatcher(aExtAddress, Router::kInStateValid));
382 }
383 
GetNeighbor(const Mac::Address & aMacAddress)384 Router *RouterTable::GetNeighbor(const Mac::Address &aMacAddress)
385 {
386     return FindRouter(Router::AddressMatcher(aMacAddress, Router::kInStateValid));
387 }
388 
GetRouter(uint8_t aRouterId) const389 const Router *RouterTable::GetRouter(uint8_t aRouterId) const
390 {
391     const Router *router = nullptr;
392     uint16_t      rloc16;
393 
394     // Skip if invalid router id is passed.
395     VerifyOrExit(aRouterId < Mle::kInvalidRouterId);
396 
397     rloc16 = Mle::Mle::Rloc16FromRouterId(aRouterId);
398     router = FindRouter(Router::AddressMatcher(rloc16, Router::kInStateAny));
399 
400 exit:
401     return router;
402 }
403 
GetRouter(const Mac::ExtAddress & aExtAddress)404 Router *RouterTable::GetRouter(const Mac::ExtAddress &aExtAddress)
405 {
406     return FindRouter(Router::AddressMatcher(aExtAddress, Router::kInStateAny));
407 }
408 
GetRouterInfo(uint16_t aRouterId,Router::Info & aRouterInfo)409 Error RouterTable::GetRouterInfo(uint16_t aRouterId, Router::Info &aRouterInfo)
410 {
411     Error   error = kErrorNone;
412     Router *router;
413     uint8_t routerId;
414 
415     if (aRouterId <= Mle::kMaxRouterId)
416     {
417         routerId = static_cast<uint8_t>(aRouterId);
418     }
419     else
420     {
421         VerifyOrExit(Mle::Mle::IsActiveRouter(aRouterId), error = kErrorInvalidArgs);
422         routerId = Mle::Mle::RouterIdFromRloc16(aRouterId);
423         VerifyOrExit(routerId <= Mle::kMaxRouterId, error = kErrorInvalidArgs);
424     }
425 
426     router = GetRouter(routerId);
427     VerifyOrExit(router != nullptr, error = kErrorNotFound);
428 
429     aRouterInfo.SetFrom(*router);
430 
431 exit:
432     return error;
433 }
434 
GetLeader(void)435 Router *RouterTable::GetLeader(void)
436 {
437     return GetRouter(Get<Mle::MleRouter>().GetLeaderId());
438 }
439 
GetLeaderAge(void) const440 uint32_t RouterTable::GetLeaderAge(void) const
441 {
442     return (mActiveRouterCount > 0) ? Time::MsecToSec(TimerMilli::GetNow() - mRouterIdSequenceLastUpdated) : 0xffffffff;
443 }
444 
GetNeighborCount(void) const445 uint8_t RouterTable::GetNeighborCount(void) const
446 {
447     uint8_t count = 0;
448 
449     for (const Router *router = GetFirstEntry(); router != nullptr; router = GetNextEntry(router))
450     {
451         if (router->IsStateValid())
452         {
453             count++;
454         }
455     }
456 
457     return count;
458 }
459 
GetLinkCost(Router & aRouter)460 uint8_t RouterTable::GetLinkCost(Router &aRouter)
461 {
462     uint8_t rval = Mle::kMaxRouteCost;
463 
464     VerifyOrExit(aRouter.GetRloc16() != Get<Mle::MleRouter>().GetRloc16() && aRouter.IsStateValid());
465 
466     rval = aRouter.GetLinkInfo().GetLinkQuality();
467 
468     if (rval > aRouter.GetLinkQualityOut())
469     {
470         rval = aRouter.GetLinkQualityOut();
471     }
472 
473     rval = Mle::MleRouter::LinkQualityToCost(rval);
474 
475 exit:
476     return rval;
477 }
478 
UpdateRouterIdSet(uint8_t aRouterIdSequence,const Mle::RouterIdSet & aRouterIdSet)479 void RouterTable::UpdateRouterIdSet(uint8_t aRouterIdSequence, const Mle::RouterIdSet &aRouterIdSet)
480 {
481     mRouterIdSequence            = aRouterIdSequence;
482     mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
483 
484     VerifyOrExit(mAllocatedRouterIds != aRouterIdSet);
485 
486     for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
487     {
488         // If was allocated but removed in new Router Id Set
489         if (IsAllocated(routerId) && !aRouterIdSet.Contains(routerId))
490         {
491             Router *router = GetRouter(routerId);
492 
493             OT_ASSERT(router != nullptr);
494             router->SetNextHop(Mle::kInvalidRouterId);
495             RemoveRouterLink(*router);
496 
497             mAllocatedRouterIds.Remove(routerId);
498         }
499     }
500 
501     mAllocatedRouterIds = aRouterIdSet;
502     UpdateAllocation();
503     Get<Mle::MleRouter>().ResetAdvertiseInterval();
504 
505 exit:
506     return;
507 }
508 
HandleTimeTick(void)509 void RouterTable::HandleTimeTick(void)
510 {
511     Mle::MleRouter &mle = Get<Mle::MleRouter>();
512 
513     if (mle.IsLeader())
514     {
515         // update router id sequence
516         if (GetLeaderAge() >= Mle::kRouterIdSequencePeriod)
517         {
518             mRouterIdSequence++;
519             mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
520         }
521 
522         for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
523         {
524             if (mRouterIdReuseDelay[routerId] > 0)
525             {
526                 mRouterIdReuseDelay[routerId]--;
527             }
528         }
529     }
530 }
531 
532 } // namespace ot
533 
534 #endif // OPENTHREAD_FTD
535