mirror of
https://github.com/espressif/openthread.git
synced 2026-08-09 04:07:47 +00:00
[meshcop-tlvs] new methods for parsing Channel Mask Entry (#2705)
This commit adds new methods/classes related to parsing of Channel Mask Entries in a Channel Mask TLV. A new class `ChannelMask0Entry` is added for a Channel Mask Entry with Channel Page 0. `ChannelMaskTlv::GetFirstEntry()` and`ChannelMaskEntry:GetNext()` methods are added and can be used to iterate through all the entries in a Channel Mask TLV. New method `ChannelMaskTlv::GetMask0Entry()` can be used to search among all entries to find the one with Channel Page 0 (if one exist).
This commit is contained in:
committed by
Jonathan Hui
parent
7f901cf9c7
commit
243642272a
@@ -144,22 +144,13 @@ void Dataset::Get(otOperationalDataset &aDataset) const
|
||||
|
||||
case Tlv::kChannelMask:
|
||||
{
|
||||
uint8_t length = cur->GetLength();
|
||||
const uint8_t *entry = reinterpret_cast<const uint8_t *>(cur) + sizeof(Tlv);
|
||||
const uint8_t *entryEnd = entry + length;
|
||||
const ChannelMaskTlv * tlv = static_cast<const ChannelMaskTlv *>(cur);
|
||||
const ChannelMask0Entry *entry = tlv->GetMask0Entry();
|
||||
|
||||
while (entry < entryEnd)
|
||||
if (entry != NULL)
|
||||
{
|
||||
if (reinterpret_cast<const ChannelMaskEntry *>(entry)->GetChannelPage() == 0)
|
||||
{
|
||||
const ChannelMask0Tlv *tlv = static_cast<const ChannelMask0Tlv *>(cur);
|
||||
aDataset.mChannelMaskPage0 = tlv->GetMask();
|
||||
aDataset.mIsChannelMaskPage0Set = true;
|
||||
break;
|
||||
}
|
||||
|
||||
entry +=
|
||||
(reinterpret_cast<const ChannelMaskEntry *>(entry)->GetMaskLength() + sizeof(ChannelMaskEntry));
|
||||
aDataset.mChannelMaskPage0 = entry->GetMask();
|
||||
aDataset.mIsChannelMaskPage0Set = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -113,5 +113,49 @@ void SteeringDataTlv::ComputeBloomFilter(const otExtAddress &aJoinerId)
|
||||
SetBit(ansi.Get() % GetNumBits());
|
||||
}
|
||||
|
||||
const ChannelMaskEntry *ChannelMaskEntry::GetNext(const Tlv *aChannelMaskTlv) const
|
||||
{
|
||||
const uint8_t *entry = reinterpret_cast<const uint8_t *>(this) + GetSize();
|
||||
const uint8_t *end = aChannelMaskTlv->GetValue() + aChannelMaskTlv->GetSize();
|
||||
|
||||
return (entry < end) ? reinterpret_cast<const ChannelMaskEntry *>(entry) : NULL;
|
||||
}
|
||||
|
||||
const ChannelMaskEntry *ChannelMaskTlv::GetFirstEntry(void) const
|
||||
{
|
||||
const ChannelMaskEntry *entry = NULL;
|
||||
|
||||
VerifyOrExit(GetLength() >= sizeof(ChannelMaskEntry));
|
||||
|
||||
entry = reinterpret_cast<const ChannelMaskEntry *>(GetValue());
|
||||
VerifyOrExit(GetLength() >= entry->GetSize(), entry = NULL);
|
||||
|
||||
exit:
|
||||
return entry;
|
||||
}
|
||||
|
||||
const ChannelMask0Entry *ChannelMaskTlv::GetMask0Entry(void) const
|
||||
{
|
||||
const ChannelMask0Entry *page0Entry = NULL;
|
||||
|
||||
for (const ChannelMaskEntry *entry = GetFirstEntry(); entry != NULL; entry = entry->GetNext(this))
|
||||
{
|
||||
if (entry->GetChannelPage() == 0)
|
||||
{
|
||||
page0Entry = static_cast<const ChannelMask0Entry *>(entry);
|
||||
|
||||
if (page0Entry->IsValid())
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
page0Entry = NULL;
|
||||
|
||||
exit:
|
||||
return page0Entry;
|
||||
}
|
||||
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
|
||||
@@ -1330,6 +1330,14 @@ public:
|
||||
*/
|
||||
void SetMaskLength(uint8_t aMaskLength) { mMaskLength = aMaskLength; }
|
||||
|
||||
/**
|
||||
* This method returns the total size of this Channel Mask Entry including the mask.
|
||||
*
|
||||
* @returns The total size of this entry (number of bytes).
|
||||
*
|
||||
*/
|
||||
uint8_t GetSize(void) const { return sizeof(ChannelMaskEntry) + mMaskLength; }
|
||||
|
||||
/**
|
||||
* This method clears the bit corresponding to @p aChannel in ChannelMask.
|
||||
*
|
||||
@@ -1366,11 +1374,68 @@ public:
|
||||
return (aChannel < (mMaskLength * 8)) ? ((mask[aChannel / 8] & (0x80 >> (aChannel % 8))) != 0) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets the next Channel Mask Entry in a Channel Mask TLV.
|
||||
*
|
||||
* @param[in] aChannelMaskTlv A pointer to the Channel Mask TLV to which this entry belongs.
|
||||
*
|
||||
* @returns A pointer to next Channel Mask Entry or NULL if none found.
|
||||
*
|
||||
*/
|
||||
const ChannelMaskEntry *GetNext(const Tlv *aChannelMaskTlv) const;
|
||||
|
||||
private:
|
||||
uint8_t mChannelPage;
|
||||
uint8_t mMaskLength;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Channel Mask Entry Page 0 generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ChannelMask0Entry : public ChannelMaskEntry
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the entry.
|
||||
*
|
||||
*/
|
||||
void Init(void)
|
||||
{
|
||||
SetChannelPage(0);
|
||||
SetMaskLength(sizeof(mMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the entry appears to be well-formed.
|
||||
*
|
||||
* @retval TRUE If the entry appears to be well-formed.
|
||||
* @retval FALSE If the entry does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return GetChannelPage() == 0 && GetMaskLength() == sizeof(mMask); }
|
||||
|
||||
/**
|
||||
* This method returns the Channel Mask value as a `uint32_t` bit mask.
|
||||
*
|
||||
* @returns The Channel Mask value.
|
||||
*
|
||||
*/
|
||||
uint32_t GetMask(void) const { return Reverse32(HostSwap32(mMask)); }
|
||||
|
||||
/**
|
||||
* This method sets the Channel Mask value.
|
||||
*
|
||||
* @param[in] aMask The Channel Mask value.
|
||||
*
|
||||
*/
|
||||
void SetMask(uint32_t aMask) { mMask = HostSwap32(Reverse32(aMask)); }
|
||||
|
||||
private:
|
||||
uint32_t mMask;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Channel Mask TLV generation and parsing.
|
||||
*
|
||||
@@ -1397,6 +1462,23 @@ public:
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return true; }
|
||||
|
||||
/**
|
||||
* This method gets the first Channel Mask Entry in the Channel Mask TLV.
|
||||
*
|
||||
* @returns A pointer to first Channel Mask Entry or NULL if not found.
|
||||
*
|
||||
*/
|
||||
const ChannelMaskEntry *GetFirstEntry(void) const;
|
||||
|
||||
/**
|
||||
* This method gets the Page 0 Channel Mask Entry in the Channel Mask TLV.
|
||||
*
|
||||
* @returns A pointer to Page 0 Channel Mask Entry or NULL if not found.
|
||||
*
|
||||
*/
|
||||
const ChannelMask0Entry *GetMask0Entry(void) const;
|
||||
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
@@ -1404,7 +1486,7 @@ public:
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ChannelMask0Tlv : public ChannelMaskTlv, public ChannelMaskEntry
|
||||
class ChannelMask0Tlv : public ChannelMaskTlv, public ChannelMask0Entry
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -1415,8 +1497,7 @@ public:
|
||||
{
|
||||
SetType(kChannelMask);
|
||||
SetLength(sizeof(*this) - sizeof(Tlv));
|
||||
SetChannelPage(0);
|
||||
SetMaskLength(sizeof(mMask));
|
||||
ChannelMask0Entry::Init();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1426,29 +1507,7 @@ public:
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const
|
||||
{
|
||||
return GetLength() == sizeof(*this) - sizeof(Tlv) && GetChannelPage() == 0 && GetMaskLength() == sizeof(mMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Channel Mask value.
|
||||
*
|
||||
* @returns The Channel Mask value.
|
||||
*
|
||||
*/
|
||||
uint32_t GetMask(void) const { return Reverse32(HostSwap32(mMask)); }
|
||||
|
||||
/**
|
||||
* This method sets the Channel Mask value.
|
||||
*
|
||||
* @param[in] aMask The Channel Mask value.
|
||||
*
|
||||
*/
|
||||
void SetMask(uint32_t aMask) { mMask = HostSwap32(Reverse32(aMask)); }
|
||||
|
||||
private:
|
||||
uint32_t mMask;
|
||||
bool IsValid(void) const { return GetLength() == sizeof(*this) - sizeof(Tlv) && ChannelMask0Entry::IsValid(); }
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
|
||||
+21
-13
@@ -1547,22 +1547,26 @@ exit:
|
||||
|
||||
bool Mle::PrepareAnnounceState(void)
|
||||
{
|
||||
bool shouldAnnounce = false;
|
||||
uint16_t numChannels = 0;
|
||||
const MeshCoP::ChannelMask0Tlv *channelMask;
|
||||
MeshCoP::Dataset dataset(MeshCoP::Tlv::kActiveTimestamp);
|
||||
bool shouldAnnounce = false;
|
||||
uint16_t numChannels = 0;
|
||||
const MeshCoP::ChannelMaskTlv * channelMaskTlv;
|
||||
const MeshCoP::ChannelMask0Entry *channelMaskEntry;
|
||||
MeshCoP::Dataset dataset(MeshCoP::Tlv::kActiveTimestamp);
|
||||
|
||||
VerifyOrExit((mRole != OT_DEVICE_ROLE_CHILD) && ((mDeviceMode & ModeTlv::kModeFFD) == 0) &&
|
||||
(mReattachState == kReattachStop));
|
||||
|
||||
SuccessOrExit(GetNetif().GetActiveDataset().Get(dataset));
|
||||
channelMask = static_cast<const MeshCoP::ChannelMask0Tlv *>(dataset.Get(MeshCoP::Tlv::kChannelMask));
|
||||
|
||||
VerifyOrExit(channelMask != NULL);
|
||||
channelMaskTlv = static_cast<const MeshCoP::ChannelMaskTlv *>(dataset.Get(MeshCoP::Tlv::kChannelMask));
|
||||
VerifyOrExit(channelMaskTlv != NULL);
|
||||
|
||||
channelMaskEntry = channelMaskTlv->GetMask0Entry();
|
||||
VerifyOrExit(channelMaskEntry != NULL);
|
||||
|
||||
for (uint8_t channel = OT_RADIO_CHANNEL_MIN; channel <= OT_RADIO_CHANNEL_MAX; channel++)
|
||||
{
|
||||
if (channelMask->IsChannelSet(channel))
|
||||
if (channelMaskEntry->IsChannelSet(channel))
|
||||
{
|
||||
numChannels++;
|
||||
}
|
||||
@@ -2127,18 +2131,22 @@ exit:
|
||||
|
||||
otError Mle::SendOrphanAnnounce(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
const MeshCoP::ChannelMask0Tlv *channelMask;
|
||||
MeshCoP::Dataset dataset(MeshCoP::Tlv::kActiveTimestamp);
|
||||
otError error = OT_ERROR_NONE;
|
||||
const MeshCoP::ChannelMaskTlv * channelMaskTlv;
|
||||
const MeshCoP::ChannelMask0Entry *channelMaskEntry;
|
||||
MeshCoP::Dataset dataset(MeshCoP::Tlv::kActiveTimestamp);
|
||||
|
||||
SuccessOrExit(error = GetNetif().GetActiveDataset().Get(dataset));
|
||||
|
||||
channelMask = static_cast<const MeshCoP::ChannelMask0Tlv *>(dataset.Get(MeshCoP::Tlv::kChannelMask));
|
||||
VerifyOrExit(channelMask != NULL, error = OT_ERROR_NOT_FOUND);
|
||||
channelMaskTlv = static_cast<const MeshCoP::ChannelMaskTlv *>(dataset.Get(MeshCoP::Tlv::kChannelMask));
|
||||
VerifyOrExit(channelMaskTlv != NULL, error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
channelMaskEntry = channelMaskTlv->GetMask0Entry();
|
||||
VerifyOrExit(channelMaskEntry != NULL, error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
VerifyOrExit(mAnnounceChannel <= OT_RADIO_CHANNEL_MAX, error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
while (!channelMask->IsChannelSet(mAnnounceChannel))
|
||||
while (!channelMaskEntry->IsChannelSet(mAnnounceChannel))
|
||||
{
|
||||
mAnnounceChannel++;
|
||||
VerifyOrExit(mAnnounceChannel <= OT_RADIO_CHANNEL_MAX, error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
Reference in New Issue
Block a user