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