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