Skip to content

Commit

Permalink
[network-data] enhance route lookup for ALOC destination (openthread#…
Browse files Browse the repository at this point in the history
…10509)

This commit updates `NetworkData::Leader` to enhance route lookup for
ALOC destinations. It contains the following changes:

- Adds `LookupRouteForServiceAloc()` to look up the route for a
  service ALOC. This method uses the common `CompareRouteEntries()`,
  which applies the same rules as in external route lookup.
- Adds `LookupRouteForAgentAloc()` to look up the route for DHCPv6 or
  ND agent ALOC.
- Adds `FindPrefixTlvForContextId()` to find a Prefix TLV matching a
  given Context ID (used in `GetContext()` and
  `LookupRouteForAgentAloc()`)
- Adds `LookupRouteIn()` to perform route lookup among all entries of
  a given `PrefixTlv` that match a given `EntryChecker` function
  (used for `DefaultRouteLookup()` or `LookupRouteForAgentAloc()`)
- Adds `test-031-service-aloc-route-lookup.py`.
  • Loading branch information
abtink authored Jul 16, 2024
1 parent cf5637f commit aba7aed
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 130 deletions.
83 changes: 58 additions & 25 deletions src/core/thread/network_data_leader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,34 +187,46 @@ Error Leader::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext
return (aContext.mPrefix.GetLength() > 0) ? kErrorNone : kErrorNotFound;
}

Error Leader::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const
const PrefixTlv *Leader::FindPrefixTlvForContextId(uint8_t aContextId, const ContextTlv *&aContextTlv) const
{
Error error = kErrorNotFound;
TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd());
const PrefixTlv *prefixTlv;

if (aContextId == Mle::kMeshLocalPrefixContextId)
{
GetContextForMeshLocalPrefix(aContext);
ExitNow(error = kErrorNone);
}

while ((prefixTlv = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
{
const ContextTlv *contextTlv = prefixTlv->FindSubTlv<ContextTlv>();

if ((contextTlv == nullptr) || (contextTlv->GetContextId() != aContextId))
if ((contextTlv != nullptr) && (contextTlv->GetContextId() == aContextId))
{
continue;
aContextTlv = contextTlv;
break;
}
}

prefixTlv->CopyPrefixTo(aContext.mPrefix);
aContext.mContextId = contextTlv->GetContextId();
aContext.mCompressFlag = contextTlv->IsCompress();
aContext.mIsValid = true;
ExitNow(error = kErrorNone);
return prefixTlv;
}

Error Leader::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const
{
Error error = kErrorNone;
TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd());
const PrefixTlv *prefixTlv;
const ContextTlv *contextTlv;

if (aContextId == Mle::kMeshLocalPrefixContextId)
{
GetContextForMeshLocalPrefix(aContext);
ExitNow();
}

prefixTlv = FindPrefixTlvForContextId(aContextId, contextTlv);
VerifyOrExit(prefixTlv != nullptr, error = kErrorNotFound);

prefixTlv->CopyPrefixTo(aContext.mPrefix);
aContext.mContextId = contextTlv->GetContextId();
aContext.mCompressFlag = contextTlv->IsCompress();
aContext.mIsValid = true;

exit:
return error;
}
Expand Down Expand Up @@ -299,13 +311,22 @@ Error Leader::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDest
return error;
}

template <typename EntryType> int Leader::CompareRouteEntries(const EntryType &aFirst, const EntryType &aSecond) const
int Leader::CompareRouteEntries(const BorderRouterEntry &aFirst, const BorderRouterEntry &aSecond) const
{
// `EntryType` can be `HasRouteEntry` or `BorderRouterEntry`.
return CompareRouteEntries(aFirst.GetPreference(), aFirst.GetRloc(), aSecond.GetPreference(), aSecond.GetRloc());
}

int Leader::CompareRouteEntries(const HasRouteEntry &aFirst, const HasRouteEntry &aSecond) const
{
return CompareRouteEntries(aFirst.GetPreference(), aFirst.GetRloc(), aSecond.GetPreference(), aSecond.GetRloc());
}

int Leader::CompareRouteEntries(const ServerTlv &aFirst, const ServerTlv &aSecond) const
{
return CompareRouteEntries(/* aFirstPreference */ 0, aFirst.GetServer16(), /* aSecondPreference */ 0,
aSecond.GetServer16());
}

int Leader::CompareRouteEntries(int8_t aFirstPreference,
uint16_t aFirstRloc,
int8_t aSecondPreference,
Expand Down Expand Up @@ -393,39 +414,51 @@ Error Leader::ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDestin
return error;
}

Error Leader::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) const
Error Leader::LookupRouteIn(const PrefixTlv &aPrefixTlv, EntryChecker aEntryChecker, uint16_t &aRloc16) const
{
// Iterates over all `BorderRouterEntry` associated with
// `aPrefixTlv` which also match `aEntryChecker` and determine the
// best route. For example, this is used from `DefaultRouteLookup()`
// to look up best default route.

Error error = kErrorNoRoute;
TlvIterator subTlvIterator(aPrefix);
TlvIterator subTlvIterator(aPrefixTlv);
const BorderRouterTlv *brTlv;
const BorderRouterEntry *route = nullptr;
const BorderRouterEntry *bestEntry = nullptr;

while ((brTlv = subTlvIterator.Iterate<BorderRouterTlv>()) != nullptr)
{
for (const BorderRouterEntry *entry = brTlv->GetFirstEntry(); entry <= brTlv->GetLastEntry();
entry = entry->GetNext())
{
if (!entry->IsDefaultRoute())
if (!aEntryChecker(*entry))
{
continue;
}

if (route == nullptr || CompareRouteEntries(*entry, *route) > 0)
if ((bestEntry == nullptr) || CompareRouteEntries(*entry, *bestEntry) > 0)
{
route = entry;
bestEntry = entry;
}
}
}

if (route != nullptr)
if (bestEntry != nullptr)
{
aRloc16 = route->GetRloc();
aRloc16 = bestEntry->GetRloc();
error = kErrorNone;
}

return error;
}

bool Leader::IsEntryDefaultRoute(const BorderRouterEntry &aEntry) { return aEntry.IsDefaultRoute(); }

Error Leader::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) const
{
return LookupRouteIn(aPrefix, IsEntryDefaultRoute, aRloc16);
}

Error Leader::SetNetworkData(uint8_t aVersion,
uint8_t aStableVersion,
Type aType,
Expand Down
44 changes: 20 additions & 24 deletions src/core/thread/network_data_leader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,15 +423,6 @@ class Leader : public MutableNetworkData, private NonCopyable
*/
void HandleNetworkDataRestoredAfterReset(void);

/**
* Scans network data for given Service ID and returns pointer to the respective TLV, if present.
*
* @param aServiceId Service ID to look for.
* @return Pointer to the Service TLV for given Service ID, or nullptr if not present.
*
*/
const ServiceTlv *FindServiceById(uint8_t aServiceId) const;

#endif // OPENTHREAD_FTD

#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
Expand All @@ -453,16 +444,24 @@ class Leader : public MutableNetworkData, private NonCopyable
private:
using FilterIndexes = MeshCoP::SteeringData::HashBitIndexes;

typedef bool (&EntryChecker)(const BorderRouterEntry &aEntry);

const PrefixTlv *FindNextMatchingPrefixTlv(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const;
const PrefixTlv *FindPrefixTlvForContextId(uint8_t aContextId, const ContextTlv *&aContextTlv) const;

template <typename EntryType> int CompareRouteEntries(const EntryType &aFirst, const EntryType &aSecond) const;
int CompareRouteEntries(int8_t aFirstPreference,
uint16_t aFirstRloc,
int8_t aSecondPreference,
uint16_t aSecondRloc) const;
int CompareRouteEntries(const BorderRouterEntry &aFirst, const BorderRouterEntry &aSecond) const;
int CompareRouteEntries(const HasRouteEntry &aFirst, const HasRouteEntry &aSecond) const;
int CompareRouteEntries(const ServerTlv &aFirst, const ServerTlv &aSecond) const;
int CompareRouteEntries(int8_t aFirstPreference,
uint16_t aFirstRloc,
int8_t aSecondPreference,
uint16_t aSecondRloc) const;

static bool IsEntryDefaultRoute(const BorderRouterEntry &aEntry);

Error ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDestination, uint16_t &aRloc16) const;
Error DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) const;
Error LookupRouteIn(const PrefixTlv &aPrefixTlv, EntryChecker aEntryChecker, uint16_t &aRloc16) const;
Error SteeringDataCheck(const FilterIndexes &aFilterIndexes) const;
void GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const;
Error ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, uint16_t &aValue) const;
Expand All @@ -480,13 +479,6 @@ class Leader : public MutableNetworkData, private NonCopyable
static constexpr uint8_t kMinServiceId = 0x00;
static constexpr uint8_t kMaxServiceId = 0x0f;

enum AnycastType : uint8_t
{
kAnycastDhcp6Agent,
kAnycastNdAgent,
kAnycastService,
};

class ChangedFlags
{
public:
Expand Down Expand Up @@ -571,8 +563,11 @@ class Leader : public MutableNetworkData, private NonCopyable

void HandleTimer(void);

Error AnycastLookup(uint8_t aServiceId, AnycastType aType, uint16_t &aRloc16) const;
void EvaluateRoutingCost(uint16_t aDest, uint8_t &aBestCost, uint16_t &aBestDest) const;
static bool IsEntryForDhcp6Agent(const BorderRouterEntry &aEntry);
static bool IsEntryForNdAgent(const BorderRouterEntry &aEntry);

Error LookupRouteForServiceAloc(uint16_t aAloc16, uint16_t &aRloc16) const;
Error LookupRouteForAgentAloc(uint8_t aContextId, EntryChecker aEntryChecker, uint16_t &aRloc16) const;

void RegisterNetworkData(uint16_t aRloc16, const NetworkData &aNetworkData);

Expand All @@ -582,7 +577,8 @@ class Leader : public MutableNetworkData, private NonCopyable
Error AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags);
Error AddServer(const ServerTlv &aServer, ServiceTlv &aDstService, ChangedFlags &aChangedFlags);

Error AllocateServiceId(uint8_t &aServiceId) const;
Error AllocateServiceId(uint8_t &aServiceId) const;
const ServiceTlv *FindServiceById(uint8_t aServiceId) const;

void RemoveContext(uint8_t aContextId);
void RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId);
Expand Down
Loading

0 comments on commit aba7aed

Please sign in to comment.