[netdata] enhance FindContext() methods and Lowpan::Context (#11836)

This commit enhances the `FindContext()` methods and converts the
`Lowpan::Context` struct into a class.

The `FindContext()` methods are updated as follows:
- Renamed to `FindContextForAddress()` and `FindContextForId()` to
  more accurately reflect their function.
- The return type is changed from `Error` to `void`. Success is now
  indicated by checking the `IsValid()` state of the output `Context`
  object (matching how `Lowpan` class uses the `Context`). This
  change simplifies the callers and harmonizes the context check
  across different modules.

The `Lowpan::Context` struct is converted into a class, encapsulating
its members by making them private and introducing public getters.
This commit is contained in:
Abtin Keshavarzian
2025-08-22 14:30:14 -07:00
committed by GitHub
parent 7b59c810d9
commit b6f1252bd8
12 changed files with 164 additions and 110 deletions
+7 -8
View File
@@ -61,7 +61,6 @@ void Server::HandleNotifierEvents(Events aEvents)
void Server::UpdateService(void)
{
Error error = kErrorNone;
uint16_t rloc16 = Get<Mle::Mle>().GetRloc16();
NetworkData::Iterator iterator;
NetworkData::OnMeshPrefixConfig prefixConfig;
@@ -86,9 +85,9 @@ void Server::UpdateService(void)
continue;
}
error = Get<NetworkData::Leader>().GetContext(prefixAgent.GetPrefixAsAddress(), lowpanContext);
Get<NetworkData::Leader>().FindContextForAddress(prefixAgent.GetPrefixAsAddress(), lowpanContext);
if ((error == kErrorNone) && (prefixAgent.GetContextId() == lowpanContext.mContextId))
if (lowpanContext.MatchesContextId(prefixAgent.GetContextId()))
{
// still in network data
found = true;
@@ -114,11 +113,11 @@ void Server::UpdateService(void)
continue;
}
error = Get<NetworkData::Leader>().GetContext(AsCoreType(&prefixConfig.mPrefix.mPrefix), lowpanContext);
Get<NetworkData::Leader>().FindContextForAddress(AsCoreType(&prefixConfig.mPrefix.mPrefix), lowpanContext);
if (error == kErrorNone)
if (lowpanContext.IsValid())
{
AddPrefixAgent(prefixConfig.GetPrefix(), lowpanContext);
AddPrefixAgent(prefixConfig.GetPrefix(), lowpanContext.GetContextId());
}
}
@@ -145,7 +144,7 @@ exit:
void Server::Stop(void) { IgnoreError(mSocket.Close()); }
void Server::AddPrefixAgent(const Ip6::Prefix &aIp6Prefix, const Lowpan::Context &aContext)
void Server::AddPrefixAgent(const Ip6::Prefix &aIp6Prefix, uint8_t aContextId)
{
Error error = kErrorNone;
PrefixAgent *newEntry = nullptr;
@@ -165,7 +164,7 @@ void Server::AddPrefixAgent(const Ip6::Prefix &aIp6Prefix, const Lowpan::Context
VerifyOrExit(newEntry != nullptr, error = kErrorNoBufs);
newEntry->Set(aIp6Prefix, Get<Mle::Mle>().GetMeshLocalPrefix(), aContext.mContextId);
newEntry->Set(aIp6Prefix, Get<Mle::Mle>().GetMeshLocalPrefix(), aContextId);
Get<ThreadNetif>().AddUnicastAddress(newEntry->GetAloc());
mPrefixAgentsCount++;
+1 -1
View File
@@ -167,7 +167,7 @@ private:
void UpdateService(void);
void Start(void);
void Stop(void);
void AddPrefixAgent(const Ip6::Prefix &aIp6Prefix, const Lowpan::Context &aContext);
void AddPrefixAgent(const Ip6::Prefix &aIp6Prefix, uint8_t aContextId);
Error AppendHeader(Message &aMessage, const TransactionId &aTransactionId);
Error AppendClientIdOption(Message &aMessage, const Mac::ExtAddress &aClientAddress);
Error AppendServerIdOption(Message &aMessage);
+7 -10
View File
@@ -50,7 +50,6 @@ void Agent::HandleNotifierEvents(Events aEvents)
void Agent::UpdateService(void)
{
Error error;
uint16_t rloc16 = Get<Mle::Mle>().GetRloc16();
NetworkData::Iterator iterator;
NetworkData::OnMeshPrefixConfig prefixConfig;
@@ -70,15 +69,13 @@ void Agent::UpdateService(void)
continue;
}
error = Get<NetworkData::Leader>().GetContext(AsCoreType(&prefixConfig.mPrefix.mPrefix), lowpanContext);
Get<NetworkData::Leader>().FindContextForAddress(AsCoreType(&prefixConfig.mPrefix.mPrefix), lowpanContext);
if ((error != kErrorNone) || (lowpanContext.mContextId != contextId))
if (lowpanContext.MatchesContextId(contextId))
{
continue;
found = true;
break;
}
found = true;
break;
}
if (!found)
@@ -99,11 +96,11 @@ void Agent::UpdateService(void)
continue;
}
error = Get<NetworkData::Leader>().GetContext(AsCoreType(&prefixConfig.mPrefix.mPrefix), lowpanContext);
Get<NetworkData::Leader>().FindContextForAddress(AsCoreType(&prefixConfig.mPrefix.mPrefix), lowpanContext);
if (error == kErrorNone)
if (lowpanContext.IsValid())
{
uint16_t aloc16 = Mle::Aloc16::FromNdAgentContextId(lowpanContext.mContextId);
uint16_t aloc16 = Mle::Aloc16::FromNdAgentContextId(lowpanContext.GetContextId());
mAloc.InitAsThreadOrigin();
mAloc.GetAddress().SetToAnycastLocator(Get<Mle::Mle>().GetMeshLocalPrefix(), aloc16);
+5 -4
View File
@@ -294,12 +294,13 @@ void DuaManager::HandleNotifierEvents(Events aEvents)
Mle::Mle &mle = Get<Mle::Mle>();
#if OPENTHREAD_CONFIG_DUA_ENABLE
if (aEvents.Contains(kEventThreadNetdataChanged))
if (aEvents.Contains(kEventThreadNetdataChanged) && Get<ThreadNetif>().HasUnicastAddress(GetDomainUnicastAddress()))
{
Lowpan::Context context;
// Remove a stale DUA address if any.
if (Get<ThreadNetif>().HasUnicastAddress(Get<DuaManager>().GetDomainUnicastAddress()) &&
(Get<NetworkData::Leader>().GetContext(Get<DuaManager>().GetDomainUnicastAddress(), context) != kErrorNone))
Get<NetworkData::Leader>().FindContextForAddress(GetDomainUnicastAddress(), context);
if (!context.IsValid())
{
RemoveDomainUnicastAddress();
}
+40 -20
View File
@@ -38,6 +38,28 @@
namespace ot {
namespace Lowpan {
//---------------------------------------------------------------------------------------------------------------------
// Context
void Context::InitForMeshLocalPrefix(Instance &aInstance)
{
mIsValid = true;
mCompressFlag = true;
mContextId = Mle::kMeshLocalPrefixContextId;
mPrefix.Set(aInstance.Get<Mle::Mle>().GetMeshLocalPrefix());
}
void Context::InitFrom(const NetworkData::PrefixTlv &aPrefixTlv, const NetworkData::ContextTlv &aContextTlv)
{
mIsValid = true;
mCompressFlag = aContextTlv.IsCompress();
mContextId = aContextTlv.GetContextId();
aPrefixTlv.CopyPrefixTo(mPrefix);
}
//---------------------------------------------------------------------------------------------------------------------
// Lowpan
Lowpan::Lowpan(Instance &aInstance)
: InstanceLocator(aInstance)
{
@@ -45,17 +67,14 @@ Lowpan::Lowpan(Instance &aInstance)
void Lowpan::FindContextForId(uint8_t aContextId, Context &aContext) const
{
if (Get<NetworkData::Leader>().GetContext(aContextId, aContext) != kErrorNone)
{
aContext.Clear();
}
Get<NetworkData::Leader>().FindContextForId(aContextId, aContext);
}
void Lowpan::FindContextToCompressAddress(const Ip6::Address &aIp6Address, Context &aContext) const
{
Error error = Get<NetworkData::Leader>().GetContext(aIp6Address, aContext);
Get<NetworkData::Leader>().FindContextForAddress(aIp6Address, aContext);
if ((error != kErrorNone) || !aContext.mCompressFlag)
if (!aContext.GetCompressFlag())
{
aContext.Clear();
}
@@ -79,7 +98,7 @@ Error Lowpan::ComputeIid(const Mac::Address &aMacAddr, const Context &aContext,
ExitNow(error = kErrorParse);
}
aIid.ApplyPrefix(aContext.mPrefix);
aIid.ApplyPrefix(aContext.GetPrefix());
exit:
return error;
@@ -179,8 +198,8 @@ Error Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, F
// Check if multicast address can be compressed using Context ID 0 (mesh local prefix)
FindContextForId(0, multicastContext);
if (multicastContext.mPrefix.GetLength() == aIpAddr.mFields.m8[3] &&
memcmp(multicastContext.mPrefix.GetBytes(), aIpAddr.mFields.m8 + 4, 8) == 0)
if (multicastContext.GetPrefix().GetLength() == aIpAddr.mFields.m8[3] &&
memcmp(multicastContext.GetPrefix().GetBytes(), aIpAddr.mFields.m8 + 4, 8) == 0)
{
aHcCtl |= kHcDstAddrContext | kHcDstAddrMode0;
SuccessOrExit(error = aFrameBuilder.AppendBytes(aIpAddr.mFields.m8 + 1, 2));
@@ -252,10 +271,11 @@ Error Lowpan::Compress(Message &aMessage,
SuccessOrExit(error = aFrameBuilder.AppendBigEndianUint16(hcCtl));
// Context Identifier
if (srcContext.mContextId != 0 || dstContext.mContextId != 0)
if (srcContext.GetContextId() != 0 || dstContext.GetContextId() != 0)
{
hcCtl |= kHcContextId;
SuccessOrExit(error = aFrameBuilder.AppendUint8(((srcContext.mContextId << 4) | dstContext.mContextId) & 0xff));
SuccessOrExit(
error = aFrameBuilder.AppendUint8(((srcContext.GetContextId() << 4) | dstContext.GetContextId()) & 0xff));
}
dscp = ((ip6HeaderBytes[0] << 2) & 0x3c) | (ip6HeaderBytes[1] >> 6);
@@ -341,7 +361,7 @@ Error Lowpan::Compress(Message &aMessage,
SuccessOrExit(
error = CompressSourceIid(aMacAddrs.mSource, ip6Header.GetSource(), srcContext, hcCtl, aFrameBuilder));
}
else if (srcContext.mIsValid)
else if (srcContext.IsValid())
{
hcCtl |= kHcSrcAddrContext;
SuccessOrExit(
@@ -362,7 +382,7 @@ Error Lowpan::Compress(Message &aMessage,
SuccessOrExit(error = CompressDestinationIid(aMacAddrs.mDestination, ip6Header.GetDestination(), dstContext,
hcCtl, aFrameBuilder));
}
else if (dstContext.mIsValid)
else if (dstContext.IsValid())
{
hcCtl |= kHcDstAddrContext;
SuccessOrExit(error = CompressDestinationIid(aMacAddrs.mDestination, ip6Header.GetDestination(), dstContext,
@@ -716,8 +736,8 @@ Error Lowpan::DecompressBaseHeader(Ip6::Header &aIp6Header,
}
else
{
VerifyOrExit(srcContext.mIsValid);
aIp6Header.GetSource().SetPrefix(srcContext.mPrefix);
VerifyOrExit(srcContext.IsValid());
aIp6Header.GetSource().SetPrefix(srcContext.GetPrefix());
}
}
@@ -756,8 +776,8 @@ Error Lowpan::DecompressBaseHeader(Ip6::Header &aIp6Header,
}
else
{
VerifyOrExit(dstContext.mIsValid);
aIp6Header.GetDestination().SetPrefix(dstContext.mPrefix);
VerifyOrExit(dstContext.IsValid());
aIp6Header.GetDestination().SetPrefix(dstContext.GetPrefix());
}
}
else
@@ -795,10 +815,10 @@ Error Lowpan::DecompressBaseHeader(Ip6::Header &aIp6Header,
switch (hcCtl & kHcDstAddrModeMask)
{
case 0:
VerifyOrExit(dstContext.mIsValid);
VerifyOrExit(dstContext.IsValid());
SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 1, 2));
aIp6Header.GetDestination().mFields.m8[3] = dstContext.mPrefix.GetLength();
memcpy(aIp6Header.GetDestination().mFields.m8 + 4, dstContext.mPrefix.GetBytes(), 8);
aIp6Header.GetDestination().mFields.m8[3] = dstContext.GetPrefix().GetLength();
memcpy(aIp6Header.GetDestination().mFields.m8 + 4, dstContext.GetPrefix().GetBytes(), 8);
SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 12, 4));
break;
+60 -6
View File
@@ -47,9 +47,14 @@
#include "net/ip6.hpp"
#include "net/ip6_address.hpp"
#include "net/ip6_types.hpp"
#include "thread/network_data_tlvs.hpp"
namespace ot {
namespace NetworkData {
class Leader;
}
/**
* @addtogroup core-6lowpan
*
@@ -68,14 +73,63 @@ namespace ot {
namespace Lowpan {
/**
* Represents a LOWPAN_IPHC Context.
* Represents a 6LoWPAN IPHC Context.
*/
struct Context : public Clearable<Context>
class Context : public Clearable<Context>
{
Ip6::Prefix mPrefix; ///< The Prefix
uint8_t mContextId; ///< The Context ID.
bool mCompressFlag; ///< The Context compression flag.
bool mIsValid; ///< Indicates whether the context is valid.
friend class ot::NetworkData::Leader;
public:
/**
* Indicates whether the context entry is valid.
*
* @retval TRUE The context is valid and can be used.
* @retval FALSE The context is not valid.
*/
bool IsValid(void) const { return mIsValid; }
/**
* Gets the IPv6 prefix associated with this context.
*
* @returns The IPv6 prefix.
*/
const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
/**
* Gets the Context ID.
*
* @returns The Context ID.
*/
uint8_t GetContextId(void) const { return mContextId; }
/**
* Gets the context compression flag.
*
* This flag indicates whether this context can be used for 6LoWPAN IPHC compression.
*
* @retval TRUE Context compression is enabled.
* @retval FALSE Context compression is disabled.
*/
bool GetCompressFlag(void) const { return mCompressFlag; }
/**
* Checks whether this context is valid and matches a given Context ID.
*
* @param[in] aContextId The Context ID to match.
*
* @retval TRUE This context is valid and its ID matches @p aContextId.
* @retval FALSE This context is not valid or its ID does not match.
*/
bool MatchesContextId(uint8_t aContextId) const { return mIsValid && (mContextId == aContextId); }
private:
void InitForMeshLocalPrefix(Instance &aInstance);
void InitFrom(const NetworkData::PrefixTlv &aPrefixTlv, const NetworkData::ContextTlv &aContextTlv);
Ip6::Prefix mPrefix;
uint8_t mContextId;
bool mCompressFlag : 1;
bool mIsValid : 1;
};
/**
+4 -2
View File
@@ -4660,9 +4660,11 @@ Error Mle::TxMessage::AppendAddressRegistrationEntry(const Ip6::Address &aAddres
{
Lowpan::Context context;
if ((Get<NetworkData::Leader>().GetContext(aAddress, context) == kErrorNone) && context.mCompressFlag)
Get<NetworkData::Leader>().FindContextForAddress(aAddress, context);
if (context.IsValid() && context.GetCompressFlag())
{
ctlByte = AddressRegistrationTlv::ControlByteFor(context.mContextId);
ctlByte = AddressRegistrationTlv::ControlByteFor(context.GetContextId());
}
}
+4 -2
View File
@@ -1910,14 +1910,16 @@ Error Mle::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
IgnoreError(aRxInfo.mMessage.Read(offsetRange, address.GetIid()));
offsetRange.AdvanceOffset(sizeof(Ip6::InterfaceIdentifier));
if (Get<NetworkData::Leader>().GetContext(contextId, context) != kErrorNone)
Get<NetworkData::Leader>().FindContextForId(contextId, context);
if (!context.IsValid())
{
LogWarn("Failed to get context %u for compressed address from child 0x%04x", contextId,
aChild.GetRloc16());
continue;
}
address.SetPrefix(context.mPrefix);
address.SetPrefix(context.GetPrefix());
}
else
{
+11 -27
View File
@@ -158,16 +158,16 @@ const PrefixTlv *Leader::FindNextMatchingPrefixTlv(const Ip6::Address &aAddress,
return prefixTlv;
}
Error Leader::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const
void Leader::FindContextForAddress(const Ip6::Address &aAddress, Lowpan::Context &aContext) const
{
const PrefixTlv *prefixTlv = nullptr;
const ContextTlv *contextTlv;
aContext.mPrefix.SetLength(0);
aContext.Clear();
if (Get<Mle::Mle>().IsMeshLocalAddress(aAddress))
{
GetContextForMeshLocalPrefix(aContext);
aContext.InitForMeshLocalPrefix(GetInstance());
}
while ((prefixTlv = FindNextMatchingPrefixTlv(aAddress, prefixTlv)) != nullptr)
@@ -181,14 +181,9 @@ Error Leader::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext
if (prefixTlv->GetPrefixLength() > aContext.mPrefix.GetLength())
{
prefixTlv->CopyPrefixTo(aContext.mPrefix);
aContext.mContextId = contextTlv->GetContextId();
aContext.mCompressFlag = contextTlv->IsCompress();
aContext.mIsValid = true;
aContext.InitFrom(*prefixTlv, *contextTlv);
}
}
return (aContext.mPrefix.GetLength() > 0) ? kErrorNone : kErrorNotFound;
}
const PrefixTlv *Leader::FindPrefixTlvForContextId(uint8_t aContextId, const ContextTlv *&aContextTlv) const
@@ -210,37 +205,26 @@ const PrefixTlv *Leader::FindPrefixTlvForContextId(uint8_t aContextId, const Con
return prefixTlv;
}
Error Leader::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const
void Leader::FindContextForId(uint8_t aContextId, Lowpan::Context &aContext) const
{
Error error = kErrorNone;
TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd());
const PrefixTlv *prefixTlv;
const ContextTlv *contextTlv;
aContext.Clear();
if (aContextId == Mle::kMeshLocalPrefixContextId)
{
GetContextForMeshLocalPrefix(aContext);
aContext.InitForMeshLocalPrefix(GetInstance());
ExitNow();
}
prefixTlv = FindPrefixTlvForContextId(aContextId, contextTlv);
VerifyOrExit(prefixTlv != nullptr, error = kErrorNotFound);
VerifyOrExit(prefixTlv != nullptr);
prefixTlv->CopyPrefixTo(aContext.mPrefix);
aContext.mContextId = contextTlv->GetContextId();
aContext.mCompressFlag = contextTlv->IsCompress();
aContext.mIsValid = true;
aContext.InitFrom(*prefixTlv, *contextTlv);
exit:
return error;
}
void Leader::GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const
{
aContext.mPrefix.Set(Get<Mle::Mle>().GetMeshLocalPrefix());
aContext.mContextId = Mle::kMeshLocalPrefixContextId;
aContext.mCompressFlag = true;
aContext.mIsValid = true;
return;
}
bool Leader::IsOnMesh(const Ip6::Address &aAddress) const
+13 -12
View File
@@ -107,26 +107,28 @@ public:
uint8_t GetVersion(Type aType) const { return (aType == kFullSet) ? mVersion : mStableVersion; }
/**
* Retrieves the 6LoWPAN Context information based on a given IPv6 address.
* Retrieves the 6LoWPAN Context information for a given IPv6 address.
*
* @param[in] aAddress A reference to an IPv6 address.
* @param[out] aContext A reference to 6LoWPAN Context information.
* If there multiple matching prefixes in the Network Data, the longest one is used.
*
* @retval kErrorNone Successfully retrieved 6LoWPAN Context information.
* @retval kErrorNotFound Could not find the 6LoWPAN Context information.
* If no matching context is found, the @p aContext structure is marked as invalid (i.e., `aContext.mIsValid` will
* be false).
*
* @param[in] aAddress The IPv6 address.
* @param[out] aContext A 6LoWPAN Context information to output the information.
*/
Error GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const;
void FindContextForAddress(const Ip6::Address &aAddress, Lowpan::Context &aContext) const;
/**
* Retrieves the 6LoWPAN Context information based on a given Context ID.
*
* @param[in] aContextId The Context ID value.
* @param[out] aContext A reference to the 6LoWPAN Context information.
* If no context matching @p aContextId is found, the @p aContext structure is marked as invalid (i.e.,
* `aContext.mIsValid` will be false).
*
* @retval kErrorNone Successfully retrieved 6LoWPAN Context information.
* @retval kErrorNotFound Could not find the 6LoWPAN Context information.
* @param[in] aContextId The Context ID.
* @param[out] aContext A `Lowpan::Context` structure to output the information.
*/
Error GetContext(uint8_t aContextId, Lowpan::Context &aContext) const;
void FindContextForId(uint8_t aContextId, Lowpan::Context &aContext) const;
/**
* Indicates whether or not the given IPv6 address is on-mesh.
@@ -447,7 +449,6 @@ private:
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;
void SignalNetDataChanged(void);
const CommissioningDataTlv *FindCommissioningData(void) const;
+6 -6
View File
@@ -365,14 +365,14 @@ bool Slaac::UpdateContextIdFor(SlaacAddress &aSlaacAddress)
{
bool didChange = false;
Lowpan::Context context;
uint8_t contextId;
if (Get<NetworkData::Leader>().GetContext(aSlaacAddress.GetAddress(), context) != kErrorNone)
{
context.mContextId = SlaacAddress::kInvalidContextId;
}
Get<NetworkData::Leader>().FindContextForAddress(aSlaacAddress.GetAddress(), context);
VerifyOrExit(context.mContextId != aSlaacAddress.GetContextId());
aSlaacAddress.SetContextId(context.mContextId);
contextId = context.IsValid() ? context.GetContextId() : SlaacAddress::kInvalidContextId;
VerifyOrExit(contextId != aSlaacAddress.GetContextId());
aSlaacAddress.SetContextId(contextId);
didChange = true;
exit:
+6 -12
View File
@@ -40,18 +40,14 @@
namespace ot {
class TestIphcVector
class TestIphcVector : public Clearable<TestIphcVector>
{
public:
enum
{
kContextUnused = 255,
kPayloadMaxLength = 512
};
struct Payload
{
uint8_t mData[kPayloadMaxLength];
static constexpr uint16_t kMaxLength = 512;
uint8_t mData[kMaxLength];
uint16_t mLength;
};
@@ -60,10 +56,8 @@ public:
*/
explicit TestIphcVector(const char *aTestName)
{
memset(reinterpret_cast<void *>(this), 0, sizeof(TestIphcVector));
mTestName = aTestName;
mSrcContext.mContextId = kContextUnused;
mDstContext.mContextId = kContextUnused;
Clear();
mTestName = aTestName;
}
/**