mirror of
https://github.com/espressif/openthread.git
synced 2026-08-14 06:37:46 +00:00
[mle] simplify parsing of Address Registration TLV entries (#8963)
This commit adds `ProcessAddressRegistrationTlv()` method which finds an Address Registration TLV in a received MLE messages from a child and processes its entries updating the child's registered addresses.
This commit is contained in:
@@ -1785,26 +1785,28 @@ exit:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Error MleRouter::UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, uint16_t aLength, Child &aChild)
|
Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
|
||||||
{
|
{
|
||||||
Error error = kErrorNone;
|
Error error;
|
||||||
AddressRegistrationEntry entry;
|
uint16_t offset;
|
||||||
Ip6::Address address;
|
uint16_t length;
|
||||||
Lowpan::Context context;
|
uint16_t endOffset;
|
||||||
uint8_t registeredCount = 0;
|
uint8_t count = 0;
|
||||||
uint8_t storedCount = 0;
|
uint8_t storedCount = 0;
|
||||||
uint16_t end = aOffset + aLength;
|
|
||||||
#if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
|
#if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
|
||||||
Ip6::Address oldDua;
|
Ip6::Address oldDua;
|
||||||
const Ip6::Address *oldDuaPtr = nullptr;
|
const Ip6::Address *oldDuaPtr = nullptr;
|
||||||
bool hasDua = false;
|
bool hasDua = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||||
Ip6::Address oldMlrRegisteredAddresses[kMaxChildIpAddresses - 1];
|
Ip6::Address oldMlrRegisteredAddresses[kMaxChildIpAddresses - 1];
|
||||||
uint16_t oldMlrRegisteredAddressNum = 0;
|
uint16_t oldMlrRegisteredAddressNum = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SuccessOrExit(error = Tlv::FindTlvValueOffset(aRxInfo.mMessage, Tlv::kAddressRegistration, offset, length));
|
||||||
|
|
||||||
|
endOffset = offset + length;
|
||||||
|
|
||||||
#if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
|
#if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
|
||||||
if ((oldDuaPtr = aChild.GetDomainUnicastAddress()) != nullptr)
|
if ((oldDuaPtr = aChild.GetDomainUnicastAddress()) != nullptr)
|
||||||
{
|
{
|
||||||
@@ -1831,36 +1833,47 @@ Error MleRouter::UpdateChildAddresses(const Message &aMessage, uint16_t aOffset,
|
|||||||
|
|
||||||
aChild.ClearIp6Addresses();
|
aChild.ClearIp6Addresses();
|
||||||
|
|
||||||
while (aOffset < end)
|
while (offset < endOffset)
|
||||||
{
|
{
|
||||||
uint8_t len;
|
uint8_t controlByte;
|
||||||
|
Ip6::Address address;
|
||||||
|
|
||||||
// read out the control field
|
// Read out the control byte (first byte in entry)
|
||||||
SuccessOrExit(error = aMessage.Read(aOffset, &entry, sizeof(uint8_t)));
|
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, controlByte));
|
||||||
|
offset++;
|
||||||
|
count++;
|
||||||
|
|
||||||
len = entry.GetLength();
|
address.Clear();
|
||||||
|
|
||||||
SuccessOrExit(error = aMessage.Read(aOffset, &entry, len));
|
if (AddressRegistrationTlv::IsEntryCompressed(controlByte))
|
||||||
|
|
||||||
aOffset += len;
|
|
||||||
registeredCount++;
|
|
||||||
|
|
||||||
if (entry.IsCompressed())
|
|
||||||
{
|
{
|
||||||
if (Get<NetworkData::Leader>().GetContext(entry.GetContextId(), context) != kErrorNone)
|
// Compressed entry contains IID with the 64-bit prefix
|
||||||
|
// determined from 6LoWPAN context identifier (from
|
||||||
|
// the control byte).
|
||||||
|
|
||||||
|
uint8_t contextId = AddressRegistrationTlv::GetContextId(controlByte);
|
||||||
|
Lowpan::Context context;
|
||||||
|
|
||||||
|
VerifyOrExit(offset + sizeof(Ip6::InterfaceIdentifier) <= endOffset, error = kErrorParse);
|
||||||
|
IgnoreError(aRxInfo.mMessage.Read(offset, address.GetIid()));
|
||||||
|
offset += sizeof(Ip6::InterfaceIdentifier);
|
||||||
|
|
||||||
|
if (Get<NetworkData::Leader>().GetContext(contextId, context) != kErrorNone)
|
||||||
{
|
{
|
||||||
LogWarn("Failed to get context %u for compressed address from child 0x%04x", entry.GetContextId(),
|
LogWarn("Failed to get context %u for compressed address from child 0x%04x", contextId,
|
||||||
aChild.GetRloc16());
|
aChild.GetRloc16());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
address.Clear();
|
|
||||||
address.SetPrefix(context.mPrefix);
|
address.SetPrefix(context.mPrefix);
|
||||||
address.SetIid(entry.GetIid());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
address = entry.GetIp6Address();
|
// Uncompressed entry contains the full IPv6 address.
|
||||||
|
|
||||||
|
VerifyOrExit(offset + sizeof(Ip6::Address) <= endOffset, error = kErrorParse);
|
||||||
|
IgnoreError(aRxInfo.mMessage.Read(offset, address));
|
||||||
|
offset += sizeof(Ip6::Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||||
@@ -1956,14 +1969,14 @@ Error MleRouter::UpdateChildAddresses(const Message &aMessage, uint16_t aOffset,
|
|||||||
Get<MlrManager>().UpdateProxiedSubscriptions(aChild, oldMlrRegisteredAddresses, oldMlrRegisteredAddressNum);
|
Get<MlrManager>().UpdateProxiedSubscriptions(aChild, oldMlrRegisteredAddresses, oldMlrRegisteredAddressNum);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (registeredCount == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
LogInfo("Child 0x%04x has no registered IPv6 address", aChild.GetRloc16());
|
LogInfo("Child 0x%04x has no registered IPv6 address", aChild.GetRloc16());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogInfo("Child 0x%04x has %u registered IPv6 address%s, %u address%s stored", aChild.GetRloc16(),
|
LogInfo("Child 0x%04x has %u registered IPv6 address%s, %u address%s stored", aChild.GetRloc16(), count,
|
||||||
registeredCount, (registeredCount == 1) ? "" : "es", storedCount, (storedCount == 1) ? "" : "es");
|
(count == 1) ? "" : "es", storedCount, (storedCount == 1) ? "" : "es");
|
||||||
}
|
}
|
||||||
|
|
||||||
error = kErrorNone;
|
error = kErrorNone;
|
||||||
@@ -2088,11 +2101,7 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo)
|
|||||||
|
|
||||||
if (!mode.IsFullThreadDevice())
|
if (!mode.IsFullThreadDevice())
|
||||||
{
|
{
|
||||||
uint16_t offset;
|
SuccessOrExit(error = ProcessAddressRegistrationTlv(aRxInfo, *child));
|
||||||
uint16_t length;
|
|
||||||
|
|
||||||
SuccessOrExit(error = Tlv::FindTlvValueOffset(aRxInfo.mMessage, Tlv::kAddressRegistration, offset, length));
|
|
||||||
SuccessOrExit(error = UpdateChildAddresses(aRxInfo.mMessage, offset, length, *child));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from router table
|
// Remove from router table
|
||||||
@@ -2182,8 +2191,6 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
|||||||
DeviceMode oldMode;
|
DeviceMode oldMode;
|
||||||
TlvList requestedTlvList;
|
TlvList requestedTlvList;
|
||||||
TlvList tlvList;
|
TlvList tlvList;
|
||||||
uint16_t addrOffset;
|
|
||||||
uint16_t addrLength;
|
|
||||||
bool childDidChange = false;
|
bool childDidChange = false;
|
||||||
|
|
||||||
Log(kMessageReceive, kTypeChildUpdateRequestOfChild, aRxInfo.mMessageInfo.GetPeerAddr());
|
Log(kMessageReceive, kTypeChildUpdateRequestOfChild, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||||
@@ -2246,10 +2253,15 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IPv6 Address TLV
|
// IPv6 Address TLV
|
||||||
if (Tlv::FindTlvValueOffset(aRxInfo.mMessage, Tlv::kAddressRegistration, addrOffset, addrLength) == kErrorNone)
|
switch (ProcessAddressRegistrationTlv(aRxInfo, *child))
|
||||||
{
|
{
|
||||||
SuccessOrExit(error = UpdateChildAddresses(aRxInfo.mMessage, addrOffset, addrLength, *child));
|
case kErrorNone:
|
||||||
tlvList.Add(Tlv::kAddressRegistration);
|
tlvList.Add(Tlv::kAddressRegistration);
|
||||||
|
break;
|
||||||
|
case kErrorNotFound:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ExitNow(error = kErrorParse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Leader Data
|
// Leader Data
|
||||||
@@ -2404,8 +2416,6 @@ void MleRouter::HandleChildUpdateResponse(RxInfo &aRxInfo)
|
|||||||
uint32_t mleFrameCounter;
|
uint32_t mleFrameCounter;
|
||||||
LeaderData leaderData;
|
LeaderData leaderData;
|
||||||
Child *child;
|
Child *child;
|
||||||
uint16_t addrOffset;
|
|
||||||
uint16_t addrLength;
|
|
||||||
|
|
||||||
if ((aRxInfo.mNeighbor == nullptr) || IsActiveRouter(aRxInfo.mNeighbor->GetRloc16()) ||
|
if ((aRxInfo.mNeighbor == nullptr) || IsActiveRouter(aRxInfo.mNeighbor->GetRloc16()) ||
|
||||||
!Get<ChildTable>().Contains(*aRxInfo.mNeighbor))
|
!Get<ChildTable>().Contains(*aRxInfo.mNeighbor))
|
||||||
@@ -2517,9 +2527,13 @@ void MleRouter::HandleChildUpdateResponse(RxInfo &aRxInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IPv6 Address
|
// IPv6 Address
|
||||||
if (Tlv::FindTlvValueOffset(aRxInfo.mMessage, Tlv::kAddressRegistration, addrOffset, addrLength) == kErrorNone)
|
switch (ProcessAddressRegistrationTlv(aRxInfo, *child))
|
||||||
{
|
{
|
||||||
SuccessOrExit(error = UpdateChildAddresses(aRxInfo.mMessage, addrOffset, addrLength, *child));
|
case kErrorNone:
|
||||||
|
case kErrorNotFound:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ExitNow(error = kErrorParse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Leader Data
|
// Leader Data
|
||||||
|
|||||||
@@ -630,6 +630,7 @@ private:
|
|||||||
void SetStateRouterOrLeader(DeviceRole aRole, uint16_t aRloc16, LeaderStartMode aStartMode);
|
void SetStateRouterOrLeader(DeviceRole aRole, uint16_t aRloc16, LeaderStartMode aStartMode);
|
||||||
void StopLeader(void);
|
void StopLeader(void);
|
||||||
void SynchronizeChildNetworkData(void);
|
void SynchronizeChildNetworkData(void);
|
||||||
|
Error ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild);
|
||||||
Error UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, uint16_t aLength, Child &aChild);
|
Error UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, uint16_t aLength, Child &aChild);
|
||||||
bool HasNeighborWithGoodLinkQuality(void) const;
|
bool HasNeighborWithGoodLinkQuality(void) const;
|
||||||
|
|
||||||
|
|||||||
@@ -999,6 +999,27 @@ public:
|
|||||||
*/
|
*/
|
||||||
static uint8_t ControlByteFor(uint8_t aContextId) { return kCompressed | (aContextId & kContextIdMask); }
|
static uint8_t ControlByteFor(uint8_t aContextId) { return kCompressed | (aContextId & kContextIdMask); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This static method indicates whether or not an address entry is using compressed format.
|
||||||
|
*
|
||||||
|
* @param[in] aControlByte The control byte (the first byte in the entry).
|
||||||
|
*
|
||||||
|
* @retval TRUE If the entry uses compressed format.
|
||||||
|
* @retval FALSE If the entry uses uncompressed format.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static bool IsEntryCompressed(uint8_t aControlByte) { return (aControlByte & kCompressed); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This static method gets the context ID in a compressed entry.
|
||||||
|
*
|
||||||
|
* @param[in] aControlByte The control byte (the first byte in the entry).
|
||||||
|
*
|
||||||
|
* @returns The 6LoWPAN context ID.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static uint8_t GetContextId(uint8_t aControlByte) { return (aControlByte & kContextIdMask); }
|
||||||
|
|
||||||
AddressRegistrationTlv(void) = delete;
|
AddressRegistrationTlv(void) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -1006,98 +1027,6 @@ private:
|
|||||||
static constexpr uint8_t kContextIdMask = 0xf;
|
static constexpr uint8_t kContextIdMask = 0xf;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements Address Registration Entry generation and parsing.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
OT_TOOL_PACKED_BEGIN
|
|
||||||
class AddressRegistrationEntry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* This method returns the IPv6 address or IID length.
|
|
||||||
*
|
|
||||||
* @returns The IPv6 address length if the Compressed bit is clear, or the IID length if the Compressed bit is
|
|
||||||
* set.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
uint8_t GetLength(void) const { return sizeof(mControl) + (IsCompressed() ? sizeof(mIid) : sizeof(mIp6Address)); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method indicates whether or not the Compressed flag is set.
|
|
||||||
*
|
|
||||||
* @retval TRUE If the Compressed flag is set.
|
|
||||||
* @retval FALSE If the Compressed flag is not set.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
bool IsCompressed(void) const { return (mControl & kCompressed) != 0; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method sets the Uncompressed flag.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SetUncompressed(void) { mControl = 0; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the Context ID for the compressed form.
|
|
||||||
*
|
|
||||||
* @returns The Context ID value.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
uint8_t GetContextId(void) const { return mControl & kCidMask; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method sets the Context ID value.
|
|
||||||
*
|
|
||||||
* @param[in] aContextId The Context ID value.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SetContextId(uint8_t aContextId) { mControl = kCompressed | aContextId; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the IID value.
|
|
||||||
*
|
|
||||||
* @returns The IID value.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
const Ip6::InterfaceIdentifier &GetIid(void) const { return mIid; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method sets the IID value.
|
|
||||||
*
|
|
||||||
* @param[in] aIid The IID value.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SetIid(const Ip6::InterfaceIdentifier &aIid) { mIid = aIid; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the IPv6 Address value.
|
|
||||||
*
|
|
||||||
* @returns The IPv6 Address value.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
const Ip6::Address &GetIp6Address(void) const { return mIp6Address; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method sets the IPv6 Address value.
|
|
||||||
*
|
|
||||||
* @param[in] aAddress A reference to the IPv6 Address value.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SetIp6Address(const Ip6::Address &aAddress) { mIp6Address = aAddress; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
static constexpr uint8_t kCompressed = 1 << 7;
|
|
||||||
static constexpr uint8_t kCidMask = 0xf;
|
|
||||||
|
|
||||||
uint8_t mControl;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
Ip6::InterfaceIdentifier mIid;
|
|
||||||
Ip6::Address mIp6Address;
|
|
||||||
} OT_TOOL_PACKED_FIELD;
|
|
||||||
} OT_TOOL_PACKED_END;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements Channel TLV generation and parsing.
|
* This class implements Channel TLV generation and parsing.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user