[topology] adding 'Neighbor::AddressMatcher' (#5354)

This commit adds new a type `Neighbor::AddressMactehr` which is used
to filter and find a neighbor (child/router) with a given MAC address
matching a given `Neighbor::StateFilter`. This new type helps simplify
related code in `ChildTable`/`RouterTbale`.
This commit is contained in:
Abtin Keshavarzian
2020-08-10 09:07:52 -07:00
committed by Jonathan Hui
parent 5bac12f9d6
commit 6c75a53bdc
7 changed files with 189 additions and 111 deletions
+19 -63
View File
@@ -105,13 +105,23 @@ exit:
Child *ChildTable::GetNewChild(void)
{
Child *child = mChildren;
Child *child = FindChild(Child::AddressMatcher(Child::kInStateInvalid));
VerifyOrExit(child != nullptr, OT_NOOP);
child->Clear();
exit:
return child;
}
const Child *ChildTable::FindChild(const Child::AddressMatcher &aMatcher) const
{
const Child *child = mChildren;
for (uint16_t num = mMaxChildrenAllowed; num != 0; num--, child++)
{
if (child->IsStateInvalid())
if (child->Matches(aMatcher))
{
child->Clear();
ExitNow();
}
}
@@ -124,76 +134,22 @@ exit:
Child *ChildTable::FindChild(uint16_t aRloc16, Child::StateFilter aFilter)
{
Child *child = mChildren;
for (uint16_t num = mMaxChildrenAllowed; num != 0; num--, child++)
{
if (child->MatchesFilter(aFilter) && (child->GetRloc16() == aRloc16))
{
ExitNow();
}
}
child = nullptr;
exit:
return child;
return FindChild(Child::AddressMatcher(aRloc16, aFilter));
}
Child *ChildTable::FindChild(const Mac::ExtAddress &aAddress, Child::StateFilter aFilter)
Child *ChildTable::FindChild(const Mac::ExtAddress &aExtAddress, Child::StateFilter aFilter)
{
Child *child = mChildren;
for (uint16_t num = mMaxChildrenAllowed; num != 0; num--, child++)
{
if (child->MatchesFilter(aFilter) && (child->GetExtAddress() == aAddress))
{
ExitNow();
}
}
child = nullptr;
exit:
return child;
return FindChild(Child::AddressMatcher(aExtAddress, aFilter));
}
Child *ChildTable::FindChild(const Mac::Address &aAddress, Child::StateFilter aFilter)
Child *ChildTable::FindChild(const Mac::Address &aMacAddress, Child::StateFilter aFilter)
{
Child *child = nullptr;
switch (aAddress.GetType())
{
case Mac::Address::kTypeShort:
child = FindChild(aAddress.GetShort(), aFilter);
break;
case Mac::Address::kTypeExtended:
child = FindChild(aAddress.GetExtended(), aFilter);
break;
default:
break;
}
return child;
return FindChild(Child::AddressMatcher(aMacAddress, aFilter));
}
bool ChildTable::HasChildren(Child::StateFilter aFilter) const
{
bool rval = false;
const Child *child = mChildren;
for (uint16_t num = mMaxChildrenAllowed; num != 0; num--, child++)
{
if (child->MatchesFilter(aFilter))
{
ExitNow(rval = true);
}
}
exit:
return rval;
return (FindChild(Child::AddressMatcher(aFilter)) != nullptr);
}
uint16_t ChildTable::GetNumChildren(Child::StateFilter aFilter) const
+7 -1
View File
@@ -397,7 +397,13 @@ private:
Child::StateFilter mFilter;
};
void RefreshStoredChildren(void);
Child *FindChild(const Child::AddressMatcher &aMatcher)
{
return const_cast<Child *>(const_cast<const ChildTable *>(this)->FindChild(aMatcher));
}
const Child *FindChild(const Child::AddressMatcher &aMatcher) const;
void RefreshStoredChildren(void);
uint16_t mMaxChildrenAllowed;
Child mChildren[kMaxChildren];
+19 -41
View File
@@ -342,19 +342,27 @@ uint8_t RouterTable::GetActiveLinkCount(void) const
return activeLinks;
}
const Router *RouterTable::FindRouter(const Router::AddressMatcher &aMatcher) const
{
const Router *router;
for (router = GetFirstEntry(); router != nullptr; router = GetNextEntry(router))
{
if (router->Matches(aMatcher))
{
break;
}
}
return router;
}
Router *RouterTable::GetNeighbor(uint16_t aRloc16)
{
Router *router = nullptr;
VerifyOrExit(aRloc16 != Get<Mle::MleRouter>().GetRloc16(), OT_NOOP);
for (router = GetFirstEntry(); router != nullptr; router = GetNextEntry(router))
{
if (router->IsStateValid() && router->GetRloc16() == aRloc16)
{
ExitNow();
}
}
router = FindRouter(Router::AddressMatcher(aRloc16, Router::kInStateValid));
exit:
return router;
@@ -362,20 +370,7 @@ exit:
Router *RouterTable::GetNeighbor(const Mac::ExtAddress &aExtAddress)
{
Router *router = nullptr;
VerifyOrExit(aExtAddress != Get<Mac::Mac>().GetExtAddress(), OT_NOOP);
for (router = GetFirstEntry(); router != nullptr; router = GetNextEntry(router))
{
if (router->IsStateValid() && router->GetExtAddress() == aExtAddress)
{
ExitNow();
}
}
exit:
return router;
return FindRouter(Router::AddressMatcher(aExtAddress, Router::kInStateValid));
}
const Router *RouterTable::GetRouter(uint8_t aRouterId) const
@@ -387,14 +382,7 @@ const Router *RouterTable::GetRouter(uint8_t aRouterId) const
VerifyOrExit(aRouterId < Mle::kInvalidRouterId, OT_NOOP);
rloc16 = Mle::Mle::Rloc16FromRouterId(aRouterId);
for (router = GetFirstEntry(); router != nullptr; router = GetNextEntry(router))
{
if (router->GetRloc16() == rloc16)
{
break;
}
}
router = FindRouter(Router::AddressMatcher(rloc16, Router::kInStateAny));
exit:
return router;
@@ -402,17 +390,7 @@ exit:
Router *RouterTable::GetRouter(const Mac::ExtAddress &aExtAddress)
{
Router *router = nullptr;
for (router = GetFirstEntry(); router != nullptr; router = GetNextEntry(router))
{
if (router->GetExtAddress() == aExtAddress)
{
break;
}
}
return router;
return FindRouter(Router::AddressMatcher(aExtAddress, Router::kInStateAny));
}
otError RouterTable::GetRouterInfo(uint16_t aRouterId, Router::Info &aRouterInfo)
+6
View File
@@ -423,6 +423,12 @@ private:
return const_cast<Router *>(const_cast<const RouterTable *>(this)->GetNextEntry(aRouter));
}
const Router *FindRouter(const Router::AddressMatcher &aMatcher) const;
Router * FindRouter(const Router::AddressMatcher &aMatcher)
{
return const_cast<Router *>(const_cast<const RouterTable *>(this)->FindRouter(aMatcher));
}
Router mRouters[Mle::kMaxRouters];
Mle::RouterIdSet mAllocatedRouterIds;
uint8_t mRouterIdReuseDelay[Mle::kMaxRouterId + 1];
+30
View File
@@ -41,6 +41,28 @@
namespace ot {
bool Neighbor::AddressMatcher::Matches(const Neighbor &aNeighbor) const
{
bool matches = false;
VerifyOrExit(aNeighbor.MatchesFilter(mStateFilter), OT_NOOP);
if (mShortAddress != Mac::kShortAddrInvalid)
{
VerifyOrExit(mShortAddress == aNeighbor.GetRloc16(), OT_NOOP);
}
if (mExtAddress != nullptr)
{
VerifyOrExit(*mExtAddress == aNeighbor.GetExtAddress(), OT_NOOP);
}
matches = true;
exit:
return matches;
}
void Neighbor::Info::SetFrom(const Neighbor &aNeighbor)
{
Clear();
@@ -112,6 +134,10 @@ bool Neighbor::MatchesFilter(StateFilter aFilter) const
matches = IsStateValidOrAttaching();
break;
case kInStateInvalid:
matches = IsStateInvalid();
break;
case kInStateAnyExceptInvalid:
matches = !IsStateInvalid();
break;
@@ -119,6 +145,10 @@ bool Neighbor::MatchesFilter(StateFilter aFilter) const
case kInStateAnyExceptValidOrRestoring:
matches = !IsStateValidOrRestoring();
break;
case kInStateAny:
matches = true;
break;
}
return matches;
+100 -6
View File
@@ -83,12 +83,96 @@ public:
*/
enum StateFilter
{
kInStateValid, ///< Accept child only in `kStateValid`.
kInStateValidOrRestoring, ///< Accept child with `IsStateValidOrRestoring()` being `true`.
kInStateChildIdRequest, ///< Accept child only in `Child:kStateChildIdRequest`.
kInStateValidOrAttaching, ///< Accept child with `IsStateValidOrAttaching()` being `true`.
kInStateAnyExceptInvalid, ///< Accept child in any state except `kStateInvalid`.
kInStateAnyExceptValidOrRestoring, ///< Accept child in any state except `IsStateValidOrRestoring()`.
kInStateValid, ///< Accept neighbor only in `kStateValid`.
kInStateValidOrRestoring, ///< Accept neighbor with `IsStateValidOrRestoring()` being `true`.
kInStateChildIdRequest, ///< Accept neighbor only in `Child:kStateChildIdRequest`.
kInStateValidOrAttaching, ///< Accept neighbor with `IsStateValidOrAttaching()` being `true`.
kInStateInvalid, ///< Accept neighbor only in `kStateInvalid`.
kInStateAnyExceptInvalid, ///< Accept neighbor in any state except `kStateInvalid`.
kInStateAnyExceptValidOrRestoring, ///< Accept neighbor in any state except `IsStateValidOrRestoring()`.
kInStateAny, ///< Accept neighbor in any state.
};
/**
* This class represents an Address Matcher used to find a neighbor (child/router) with a given MAC address also
* matching a given state filter.
*
*/
class AddressMatcher
{
public:
/**
* This constructor initializes the `AddressMatcher` with a given MAC short address (RCOC16) and state filter.
*
* @param[in] aShortAddress A MAC short address (RLOC16).
* @param[in] aStateFilter A state filter.
*
*/
AddressMatcher(Mac::ShortAddress aShortAddress, StateFilter aStateFilter)
: AddressMatcher(aStateFilter, aShortAddress, nullptr)
{
}
/**
* This constructor initializes the `AddressMatcher` with a given MAC extended address and state filter.
*
* @param[in] aExtAddress A MAC extended address.
* @param[in] aStateFilter A state filter.
*
*/
AddressMatcher(const Mac::ExtAddress &aExtAddress, StateFilter aStateFilter)
: AddressMatcher(aStateFilter, Mac::kShortAddrInvalid, &aExtAddress)
{
}
/**
* This constructor initializes the `AddressMatcher` with a given MAC address and state filter.
*
* @param[in] aMacAddress A MAC address.
* @param[in] aStateFilter A state filter.
*
*/
AddressMatcher(const Mac::Address &aMacAddress, StateFilter aStateFilter)
: AddressMatcher(aStateFilter,
aMacAddress.IsShort() ? aMacAddress.GetShort()
: static_cast<Mac::ShortAddress>(Mac::kShortAddrInvalid),
aMacAddress.IsExtended() ? &aMacAddress.GetExtended() : nullptr)
{
}
/**
* This constructor initializes the `AddressMatcher` with a given state filter (it accepts any address).
*
* @param[in] aStateFilter A state filter.
*
*/
explicit AddressMatcher(StateFilter aStateFilter)
: AddressMatcher(aStateFilter, Mac::kShortAddrInvalid, nullptr)
{
}
/**
* This method indicates if a given neighbor matches the address and state filter of `AddressMatcher`.
*
* @param[in] aNeighbor A neighbor.
*
* @retval TRUE Neighbor @p aNeighbor matches the address and state filter.
* @retval FALSE Neighbor @p aNeighbor does not match the address or state filter.
*
*/
bool Matches(const Neighbor &aNeighbor) const;
private:
AddressMatcher(StateFilter aStateFilter, Mac::ShortAddress aShortAddress, const Mac::ExtAddress *aExtAddress)
: mStateFilter(aStateFilter)
, mShortAddress(aShortAddress)
, mExtAddress(aExtAddress)
{
}
StateFilter mStateFilter;
Mac::ShortAddress mShortAddress;
const Mac::ExtAddress *mExtAddress;
};
/**
@@ -210,6 +294,16 @@ public:
*/
bool MatchesFilter(StateFilter aFilter) const;
/**
* This method indicates whether neighbor matches a given `AddressMatcher`.
*
* @param[in] aMatcher An `AddressMatcher` to match against.
*
* @returns TRUE if the neighbor matches the address and state filter of @p aMatcher, FALSE otherwise.
*
*/
bool Matches(const AddressMatcher &aMatcher) const { return aMatcher.Matches(*this); }
/**
* This method gets the device mode flags.
*
+8
View File
@@ -96,9 +96,17 @@ static bool StateMatchesFilter(Child::State aState, Child::StateFilter aFilter)
rval = child.IsStateValidOrAttaching();
break;
case Child::kInStateInvalid:
rval = child.IsStateInvalid();
break;
case Child::kInStateAnyExceptValidOrRestoring:
rval = !child.IsStateValidOrRestoring();
break;
case Child::kInStateAny:
rval = true;
break;
}
return rval;