mirror of
https://github.com/espressif/openthread.git
synced 2026-08-15 15:17:46 +00:00
[mac] redesign Information Element (IE) processing and generation (#13263)
This commit redesigns IEEE 802.15.4 Information Element (IE) handling by introducing dedicated subclass definitions (`CslIe`, `TimeIe`, `ConnectionIe`, `RendezvousTimeIe`, `LinkMetricsProbingIe`, etc.) inheriting from `HeaderIe` or `VendorIe`. In addition, `Mac::Frame` is updated with generic template methods: - `Has<IeType>()`: Checks if the frame contains a well-formed instance of the specified IE subclass. - `Find<IeType>()`: Finds, validates and returns a type-safe pointer to the IE. Key benefits of this redesign: - Streamlined IE Generation: Constructing and populating IEs is significantly simplified. Each subclass exposes a unified `Init()` method that cleanly computes the exact IE content length, sets the Element ID and known content (e.g. vendor OUI) in a single step. - True Encapsulation: Each IE subclass serves as the single source of truth for its Element ID (`kId`), content layout, and structural validation logic (`IsValid()`). Callers no longer pass magic ID constants or perform error-prone pointer arithmetic. - By implementing `HeaderIe::ValidateAs<IeType>()` as a static polymorphic matcher passed to `FindHeaderIe()`, the compiler devirtualizes and inlines ID match and content verifications directly into MAC frame parsing loops. - Scalable Integration: Adding new Information Elements is trivial. Defining a new subclass automatically equips MAC frame handling with type-safe search without bloating `Mac::Frame` with ad-hoc getter methods.
This commit is contained in:
@@ -205,7 +205,7 @@ otError otMacFrameGenerateEnhAck(const otRadioFrame *aFrame,
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
void otMacFrameSetCslIe(otRadioFrame *aFrame, uint16_t aCslPeriod, uint16_t aCslPhase)
|
||||
{
|
||||
static_cast<Mac::Frame *>(aFrame)->SetCslIe(aCslPeriod, aCslPhase);
|
||||
static_cast<Mac::Frame *>(aFrame)->UpdateCslIe(aCslPeriod, aCslPhase);
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
|
||||
@@ -264,42 +264,37 @@ uint8_t otMacFrameGenerateCslIeTemplate(uint8_t *aDest)
|
||||
{
|
||||
assert(aDest != nullptr);
|
||||
|
||||
reinterpret_cast<Mac::HeaderIe *>(aDest)->Init(Mac::CslIe::kHeaderIeId, sizeof(Mac::CslIe));
|
||||
reinterpret_cast<Mac::CslIe *>(aDest)->Init();
|
||||
|
||||
return sizeof(Mac::HeaderIe) + sizeof(Mac::CslIe);
|
||||
return sizeof(Mac::CslIe);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
uint8_t otMacFrameGenerateEnhAckProbingIe(uint8_t *aDest, const uint8_t *aIeData, uint8_t aIeDataLength)
|
||||
{
|
||||
uint8_t len = sizeof(Mac::VendorIeHeader) + aIeDataLength;
|
||||
Mac::LinkMetricsProbingIe *probingIe = reinterpret_cast<Mac::LinkMetricsProbingIe *>(aDest);
|
||||
|
||||
assert(aDest != nullptr);
|
||||
|
||||
reinterpret_cast<Mac::HeaderIe *>(aDest)->Init(Mac::ThreadIe::kHeaderIeId, len);
|
||||
|
||||
aDest += sizeof(Mac::HeaderIe);
|
||||
|
||||
reinterpret_cast<Mac::VendorIeHeader *>(aDest)->SetVendorOui(Mac::ThreadIe::kVendorOuiThreadCompanyId);
|
||||
reinterpret_cast<Mac::VendorIeHeader *>(aDest)->SetSubType(Mac::ThreadIe::kEnhAckProbingIe);
|
||||
probingIe->Init(aIeDataLength);
|
||||
|
||||
if (aIeData != nullptr)
|
||||
{
|
||||
aDest += sizeof(Mac::VendorIeHeader);
|
||||
memcpy(aDest, aIeData, aIeDataLength);
|
||||
probingIe->WriteMetricsDataFrom(aIeData);
|
||||
}
|
||||
|
||||
return sizeof(Mac::HeaderIe) + len;
|
||||
return probingIe->GetSize();
|
||||
}
|
||||
|
||||
void otMacFrameSetEnhAckProbingIe(otRadioFrame *aFrame, const uint8_t *aData, uint8_t aDataLen)
|
||||
{
|
||||
assert(aFrame != nullptr && aData != nullptr);
|
||||
|
||||
reinterpret_cast<Mac::Frame *>(aFrame)->SetEnhAckProbingIe(aData, aDataLen);
|
||||
reinterpret_cast<Mac::Frame *>(aFrame)->UpdateEnhAckProbingIe(aData, aDataLen);
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
static uint16_t ComputeCslPhase(uint32_t aRadioTime, otRadioContext *aRadioContext)
|
||||
{
|
||||
@@ -409,7 +404,7 @@ otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadi
|
||||
VerifyOrExit(!otMacFrameIsSecurityEnabled(aFrame) || !aFrame->mInfo.mTxInfo.mIsSecurityProcessed);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
if (static_cast<Mac::Frame *>(aFrame)->HasCslIe()) // CSL IE should be filled for every transmit attempt
|
||||
if (static_cast<Mac::Frame *>(aFrame)->Has<Mac::CslIe>()) // CSL IE should be filled for every transmit attempt
|
||||
{
|
||||
otMacFrameSetCslIe(aFrame, aRadioContext->mCslPeriod, ComputeCslPhase(aRadioTime, aRadioContext));
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ void DataPollSender::HandlePollSent(Mac::TxFrame &aFrame, Error aError)
|
||||
mPollTxFailureCounter++;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
maxRetxAttempts = aFrame.HasCslIe() ? kMaxCslPollRetxAttempts : kMaxPollRetxAttempts;
|
||||
maxRetxAttempts = aFrame.Has<Mac::CslIe>() ? kMaxCslPollRetxAttempts : kMaxPollRetxAttempts;
|
||||
#else
|
||||
maxRetxAttempts = kMaxPollRetxAttempts;
|
||||
#endif
|
||||
@@ -329,7 +329,7 @@ void DataPollSender::ProcessTxDone(const Mac::TxFrame &aFrame, const Mac::RxFram
|
||||
VerifyOrExit(aFrame.GetSecurityEnabled());
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
if (aFrame.mInfo.mTxInfo.mIsARetx && aFrame.HasCslIe())
|
||||
if (aFrame.mInfo.mTxInfo.mIsARetx && aFrame.Has<Mac::CslIe>())
|
||||
{
|
||||
// For retransmission frame, use a data poll to resync its parent with correct CSL phase
|
||||
sendDataPoll = true;
|
||||
@@ -571,7 +571,7 @@ Mac::TxFrame *DataPollSender::PrepareDataRequest(Mac::TxFrames &aTxFrames)
|
||||
Get<MessageFramer>().PrepareMacHeaders(*frame, frameInfo, nullptr);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
if (frame->HasCslIe())
|
||||
if (frame->Has<Mac::CslIe>())
|
||||
{
|
||||
// Disable frame retransmission when the data poll has CSL IE included
|
||||
aTxFrames.SetMaxFrameRetries(0);
|
||||
|
||||
+21
-38
@@ -900,7 +900,7 @@ void Mac::ProcessTransmitSecurity(TxFrame &aFrame)
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
// Transmit security will be processed after time IE content is updated.
|
||||
VerifyOrExit(aFrame.GetTimeIeOffset() == 0);
|
||||
VerifyOrExit(!aFrame.Has<TimeIe>());
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
@@ -1017,12 +1017,17 @@ void Mac::BeginTransmit(void)
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
{
|
||||
uint8_t timeIeOffset = GetTimeIeOffset(*frame);
|
||||
TimeIe *timeIe = frame->Find<TimeIe>();
|
||||
|
||||
frame->SetTimeIeOffset(timeIeOffset);
|
||||
|
||||
if (timeIeOffset != 0)
|
||||
if (timeIe == nullptr)
|
||||
{
|
||||
frame->SetTimeIeOffset(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t offset = static_cast<uint8_t>(timeIe->GetData() - frame->GetPsdu());
|
||||
|
||||
frame->SetTimeIeOffset(offset);
|
||||
frame->SetTimeSyncSeq(Get<TimeSync>().GetTimeSyncSeq());
|
||||
frame->SetNetworkTimeOffset(Get<TimeSync>().GetNetworkTimeOffset());
|
||||
}
|
||||
@@ -1303,7 +1308,7 @@ void Mac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
|
||||
ProcessCsl(*aAckFrame, dstAddr);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
if (!mRxOnWhenIdle && aFrame.HasCslIe())
|
||||
if (!mRxOnWhenIdle && aFrame.Has<CslIe>())
|
||||
{
|
||||
Get<DataPollSender>().ResetKeepAliveTimer();
|
||||
}
|
||||
@@ -2352,24 +2357,6 @@ void Mac::LogFrameTxFailure(const TxFrame &, Error, uint8_t, bool) const {}
|
||||
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
uint8_t Mac::GetTimeIeOffset(const Frame &aFrame)
|
||||
{
|
||||
uint8_t offset = 0;
|
||||
const uint8_t *base = aFrame.GetPsdu();
|
||||
const uint8_t *cur = nullptr;
|
||||
|
||||
cur = reinterpret_cast<const uint8_t *>(aFrame.GetTimeIe());
|
||||
VerifyOrExit(cur != nullptr);
|
||||
|
||||
cur += sizeof(VendorIeHeader);
|
||||
offset = static_cast<uint8_t>(cur - base);
|
||||
|
||||
exit:
|
||||
return offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
void Mac::SetCslCapable(bool aIsCslCapable)
|
||||
{
|
||||
@@ -2492,7 +2479,7 @@ void Mac::ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr)
|
||||
VerifyOrExit(aFrame.IsVersion2015());
|
||||
VerifyOrExit(aFrame.IsSecuredWith(RxFrame::kAllowKeyIdMode1));
|
||||
|
||||
csl = aFrame.GetCslIe();
|
||||
csl = aFrame.Find<CslIe>();
|
||||
VerifyOrExit(csl != nullptr);
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
@@ -2526,24 +2513,20 @@ exit:
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
|
||||
void Mac::ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor)
|
||||
{
|
||||
constexpr uint8_t kEnhAckProbingIeMaxLen = 2;
|
||||
const LinkMetricsProbingIe *probingIe = aFrame.Find<LinkMetricsProbingIe>();
|
||||
uint8_t dataLen;
|
||||
|
||||
const HeaderIe *enhAckProbingIe =
|
||||
reinterpret_cast<const HeaderIe *>(aFrame.GetThreadIe(ThreadIe::kEnhAckProbingIe));
|
||||
uint8_t dataLen;
|
||||
VerifyOrExit(probingIe != nullptr);
|
||||
|
||||
VerifyOrExit(enhAckProbingIe != nullptr);
|
||||
dataLen = probingIe->GetMetricsDataLen();
|
||||
VerifyOrExit(dataLen <= LinkMetricsProbingIe::kMaxMetricsDataLen);
|
||||
|
||||
dataLen = enhAckProbingIe->GetLength() - sizeof(VendorIeHeader);
|
||||
VerifyOrExit(dataLen <= kEnhAckProbingIeMaxLen);
|
||||
Get<LinkMetrics::Initiator>().ProcessEnhAckIeData(probingIe->GetMetricsData(), dataLen, aNeighbor);
|
||||
|
||||
Get<LinkMetrics::Initiator>().ProcessEnhAckIeData(reinterpret_cast<const uint8_t *>(enhAckProbingIe) +
|
||||
sizeof(HeaderIe) + sizeof(VendorIeHeader),
|
||||
dataLen, aNeighbor);
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
|
||||
void Mac::SetRadioFilterEnabled(bool aFilterEnabled)
|
||||
@@ -2649,13 +2632,13 @@ Error Mac::HandleWakeupFrame(const RxFrame &aFrame)
|
||||
VerifyOrExit(srcAddress.IsExtended(), error = kErrorDrop);
|
||||
|
||||
wakeupInfo.mExtAddress = srcAddress.GetExtended();
|
||||
connectionIe = aFrame.GetConnectionIe();
|
||||
connectionIe = aFrame.Find<ConnectionIe>();
|
||||
wakeupInfo.mRetryInterval = connectionIe->GetRetryInterval();
|
||||
wakeupInfo.mRetryCount = connectionIe->GetRetryCount();
|
||||
VerifyOrExit(wakeupInfo.mRetryInterval > 0 && wakeupInfo.mRetryCount > 0, error = kErrorInvalidArgs);
|
||||
|
||||
radioNowUs = otPlatRadioGetNow(&GetInstance());
|
||||
rvTimeUs = aFrame.GetRendezvousTimeIe()->GetRendezvousTime() * kUsPerTenSymbols;
|
||||
rvTimeUs = aFrame.Find<RendezvousTimeIe>()->GetRendezvousTime() * kUsPerTenSymbols;
|
||||
rvTimestampUs = aFrame.GetTimestamp() + kRadioHeaderPhrDuration + aFrame.GetLength() * kOctetDuration + rvTimeUs;
|
||||
|
||||
if (rvTimestampUs > radioNowUs + kCslRequestAhead)
|
||||
|
||||
@@ -853,10 +853,6 @@ private:
|
||||
void LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx) const;
|
||||
void LogBeacon(const char *aActionText) const;
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
uint8_t GetTimeIeOffset(const Frame &aFrame);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
void ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr);
|
||||
#endif
|
||||
|
||||
+27
-115
@@ -223,7 +223,6 @@ void TxFrame::Info::PrepareHeadersIn(TxFrame &aTxFrame) const
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
if (mAppendTimeIe)
|
||||
{
|
||||
builder.Append<HeaderIe>()->Init(TimeIe::kHeaderIeId, sizeof(TimeIe));
|
||||
builder.Append<TimeIe>()->Init();
|
||||
}
|
||||
#endif
|
||||
@@ -231,15 +230,14 @@ void TxFrame::Info::PrepareHeadersIn(TxFrame &aTxFrame) const
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
if (mAppendCslIe)
|
||||
{
|
||||
builder.Append<HeaderIe>()->Init(CslIe::kHeaderIeId, sizeof(CslIe));
|
||||
builder.Append<CslIe>();
|
||||
builder.Append<CslIe>()->Init();
|
||||
aTxFrame.SetCslIePresent(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fcf & kFcfIePresent) && ((mType == kTypeMacCmd) || !mEmptyPayload))
|
||||
{
|
||||
builder.Append<HeaderIe>()->Init(Termination2Ie::kHeaderIeId, Termination2Ie::kIeContentSize);
|
||||
builder.Append<Termination2Ie>()->Init();
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
@@ -320,14 +318,12 @@ bool Frame::IsWakeupFrame(void) const
|
||||
VerifyOrExit(keyIdMode == kKeyIdMode2);
|
||||
|
||||
// ... that has Rendezvous Time IE and Connection IE...
|
||||
VerifyOrExit(GetRendezvousTimeIe() != nullptr);
|
||||
VerifyOrExit((connectionIe = GetConnectionIe()) != nullptr);
|
||||
VerifyOrExit(Has<RendezvousTimeIe>());
|
||||
VerifyOrExit((connectionIe = Find<ConnectionIe>()) != nullptr);
|
||||
|
||||
// ... but no other IEs nor payload.
|
||||
firstIeIndex = FindHeaderIeIndex();
|
||||
VerifyOrExit(mPsdu + firstIeIndex + sizeof(HeaderIe) + RendezvousTimeIe::kIeContentSize + sizeof(HeaderIe) +
|
||||
connectionIe->GetHeaderIe()->GetLength() ==
|
||||
GetFooter());
|
||||
VerifyOrExit(mPsdu + firstIeIndex + sizeof(RendezvousTimeIe) + connectionIe->GetSize() == GetFooter());
|
||||
|
||||
result = true;
|
||||
|
||||
@@ -1090,7 +1086,7 @@ uint8_t Frame::FindPayloadIndex(void) const
|
||||
|
||||
VerifyOrExit(index + footerLength <= mLength, index = kInvalidIndex);
|
||||
|
||||
if (ie->GetId() == Termination2Ie::kHeaderIeId)
|
||||
if (ie->GetId() == Termination2Ie::kId)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -1141,6 +1137,7 @@ exit:
|
||||
const uint8_t *Frame::GetFooter(void) const { return mPsdu + mLength - GetFooterLength(); }
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
|
||||
uint8_t Frame::FindHeaderIeIndex(void) const
|
||||
{
|
||||
uint8_t index;
|
||||
@@ -1153,11 +1150,11 @@ exit:
|
||||
return index;
|
||||
}
|
||||
|
||||
const uint8_t *Frame::GetHeaderIe(uint8_t aIeId) const
|
||||
const HeaderIe *Frame::FindHeaderIe(HeaderIeMatcher aMatcher) const
|
||||
{
|
||||
uint16_t index = FindHeaderIeIndex();
|
||||
uint16_t payloadIndex = FindPayloadIndex();
|
||||
const uint8_t *header = nullptr;
|
||||
uint16_t index = FindHeaderIeIndex();
|
||||
uint16_t payloadIndex = FindPayloadIndex();
|
||||
const HeaderIe *matchedIe = nullptr;
|
||||
|
||||
// `FindPayloadIndex()` verifies that Header IE(s) in frame (if present)
|
||||
// are well-formed.
|
||||
@@ -1168,9 +1165,9 @@ const uint8_t *Frame::GetHeaderIe(uint8_t aIeId) const
|
||||
{
|
||||
const HeaderIe *ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
|
||||
|
||||
if (ie->GetId() == aIeId)
|
||||
if (aMatcher(*ie))
|
||||
{
|
||||
header = &mPsdu[index];
|
||||
matchedIe = ie;
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
@@ -1178,123 +1175,40 @@ const uint8_t *Frame::GetHeaderIe(uint8_t aIeId) const
|
||||
}
|
||||
|
||||
exit:
|
||||
return header;
|
||||
return matchedIe;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE || \
|
||||
OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
const uint8_t *Frame::GetThreadIe(uint8_t aSubType) const
|
||||
{
|
||||
uint16_t index = FindHeaderIeIndex();
|
||||
uint16_t payloadIndex = FindPayloadIndex();
|
||||
const uint8_t *header = nullptr;
|
||||
|
||||
// `FindPayloadIndex()` verifies that Header IE(s) in frame (if present)
|
||||
// are well-formed.
|
||||
VerifyOrExit((index != kInvalidIndex) && (payloadIndex != kInvalidIndex));
|
||||
|
||||
while (index < payloadIndex)
|
||||
{
|
||||
const HeaderIe *ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
|
||||
|
||||
if ((ie->GetId() == VendorIeHeader::kHeaderIeId) && (ie->GetLength() >= VendorIeHeader::kIeContentSize))
|
||||
{
|
||||
const VendorIeHeader *vendorIe = reinterpret_cast<const VendorIeHeader *>(ie->GetContent());
|
||||
|
||||
if (vendorIe->GetVendorOui() == ThreadIe::kVendorOuiThreadCompanyId && vendorIe->GetSubType() == aSubType)
|
||||
{
|
||||
header = &mPsdu[index];
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
index += ie->GetSize();
|
||||
}
|
||||
|
||||
exit:
|
||||
return header;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE ||
|
||||
// OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
void Frame::SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase)
|
||||
void Frame::UpdateCslIe(uint16_t aCslPeriod, uint16_t aCslPhase)
|
||||
{
|
||||
CslIe *csl = GetCslIe();
|
||||
CslIe *csl = Find<CslIe>();
|
||||
|
||||
VerifyOrExit(csl != nullptr);
|
||||
|
||||
csl->SetPeriod(aCslPeriod);
|
||||
csl->SetPhase(aCslPhase);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
bool Frame::HasCslIe(void) const { return GetCslIe() != nullptr; }
|
||||
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
const CslIe *Frame::GetCslIe(void) const
|
||||
{
|
||||
const uint8_t *cur;
|
||||
const CslIe *csl = nullptr;
|
||||
|
||||
cur = GetHeaderIe(CslIe::kHeaderIeId);
|
||||
VerifyOrExit(cur != nullptr);
|
||||
VerifyOrExit(reinterpret_cast<const HeaderIe *>(cur)->GetLength() >= CslIe::kIeContentSize);
|
||||
csl = reinterpret_cast<const CslIe *>(cur + sizeof(HeaderIe));
|
||||
|
||||
exit:
|
||||
return csl;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
void Frame::SetEnhAckProbingIe(const uint8_t *aValue, uint8_t aLen)
|
||||
void Frame::UpdateEnhAckProbingIe(const uint8_t *aData, uint8_t aLen)
|
||||
{
|
||||
uint8_t *cur = GetThreadIe(ThreadIe::kEnhAckProbingIe);
|
||||
LinkMetricsProbingIe *probingIe = Find<LinkMetricsProbingIe>();
|
||||
|
||||
VerifyOrExit(cur != nullptr);
|
||||
memcpy(cur + sizeof(HeaderIe) + sizeof(VendorIeHeader), aValue, aLen);
|
||||
VerifyOrExit(probingIe != nullptr);
|
||||
|
||||
VerifyOrExit(aLen >= probingIe->GetMetricsDataLen());
|
||||
probingIe->WriteMetricsDataFrom(aData);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
const TimeIe *Frame::GetTimeIe(void) const
|
||||
{
|
||||
uint16_t index = FindHeaderIeIndex();
|
||||
uint16_t payloadIndex = FindPayloadIndex();
|
||||
const TimeIe *timeIe = nullptr;
|
||||
|
||||
VerifyOrExit((index != kInvalidIndex) && (payloadIndex != kInvalidIndex));
|
||||
|
||||
while (index < payloadIndex)
|
||||
{
|
||||
const HeaderIe *ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
|
||||
|
||||
if ((ie->GetId() == VendorIeHeader::kHeaderIeId) && (ie->GetLength() >= TimeIe::kIeContentSize))
|
||||
{
|
||||
const TimeIe *vendorIe = reinterpret_cast<const TimeIe *>(ie->GetContent());
|
||||
|
||||
if (vendorIe->GetVendorOui() == TimeIe::kVendorOuiNest && vendorIe->GetSubType() == TimeIe::kVendorIeTime)
|
||||
{
|
||||
timeIe = vendorIe;
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
index += ie->GetSize();
|
||||
}
|
||||
|
||||
exit:
|
||||
return timeIe;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
uint16_t Frame::GetMtu(void) const
|
||||
@@ -1590,11 +1504,9 @@ Error TxFrame::GenerateWakeupFrame(PanId aPanId, const WakeupRequest &aWakeupReq
|
||||
IgnoreError(builder.AppendUint8(secCtl));
|
||||
builder.AppendLength(CalculateSecurityHeaderSize(secCtl) - sizeof(secCtl));
|
||||
|
||||
builder.Append<HeaderIe>()->Init(RendezvousTimeIe::kHeaderIeId, sizeof(RendezvousTimeIe));
|
||||
builder.Append<RendezvousTimeIe>();
|
||||
builder.Append<RendezvousTimeIe>()->Init();
|
||||
|
||||
builder.Append<HeaderIe>()->Init(ConnectionIe::kHeaderIeId, sizeof(ConnectionIe) + wakeupIdLength);
|
||||
builder.Append<ConnectionIe>()->Init();
|
||||
builder.Append<ConnectionIe>()->Init(wakeupIdLength);
|
||||
builder.AppendLength(wakeupIdLength);
|
||||
|
||||
builder.AppendLength(CalculateMicSize(secCtl) + GetFcsSize());
|
||||
|
||||
+42
-137
@@ -194,50 +194,7 @@ public:
|
||||
* @retval FALSE If this is not a Wake-up frame.
|
||||
*/
|
||||
bool IsWakeupFrame(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the Rendezvous Time IE of a wake-up frame.
|
||||
*
|
||||
* @returns Pointer to the Rendezvous Time IE.
|
||||
*/
|
||||
RendezvousTimeIe *GetRendezvousTimeIe(void) { return AsNonConst(AsConst(this)->GetRendezvousTimeIe()); }
|
||||
|
||||
/**
|
||||
* This method returns the Rendezvous Time IE of a wake-up frame.
|
||||
*
|
||||
* @returns Const pointer to the Rendezvous Time IE.
|
||||
*/
|
||||
const RendezvousTimeIe *GetRendezvousTimeIe(void) const
|
||||
{
|
||||
const uint8_t *ie = GetHeaderIe(RendezvousTimeIe::kHeaderIeId);
|
||||
|
||||
return (ie != nullptr &&
|
||||
reinterpret_cast<const HeaderIe *>(ie)->GetLength() >= RendezvousTimeIe::kIeContentSize)
|
||||
? reinterpret_cast<const RendezvousTimeIe *>(ie + sizeof(HeaderIe))
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Connection IE of a wake-up frame.
|
||||
*
|
||||
* @returns Pointer to the Connection IE.
|
||||
*/
|
||||
ConnectionIe *GetConnectionIe(void) { return AsNonConst(AsConst(this)->GetConnectionIe()); }
|
||||
|
||||
/**
|
||||
* This method returns the Connection IE of a wake-up frame.
|
||||
*
|
||||
* @returns Const pointer to the Connection IE.
|
||||
*/
|
||||
const ConnectionIe *GetConnectionIe(void) const
|
||||
{
|
||||
const uint8_t *ie = GetThreadIe(ConnectionIe::kThreadIeSubtype);
|
||||
|
||||
return (ie != nullptr && reinterpret_cast<const HeaderIe *>(ie)->GetLength() >= ConnectionIe::kIeContentSize)
|
||||
? reinterpret_cast<const ConnectionIe *>(ie + sizeof(HeaderIe))
|
||||
: nullptr;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the IEEE 802.15.4 Frame Version.
|
||||
@@ -613,23 +570,6 @@ public:
|
||||
*/
|
||||
const uint8_t *GetFooter(void) const;
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
|
||||
/**
|
||||
* Returns a pointer to the vendor specific Time IE.
|
||||
*
|
||||
* @returns A pointer to the Time IE, `nullptr` if not found.
|
||||
*/
|
||||
TimeIe *GetTimeIe(void) { return AsNonConst(AsConst(this)->GetTimeIe()); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the vendor specific Time IE.
|
||||
*
|
||||
* @returns A pointer to the Time IE, `nullptr` if not found.
|
||||
*/
|
||||
const TimeIe *GetTimeIe(void) const;
|
||||
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
/**
|
||||
* Indicates whether the frame contains header IEs.
|
||||
@@ -637,91 +577,67 @@ public:
|
||||
* @retval TRUE The frame contains header IEs.
|
||||
* @retval FALSE The frame contains no header IEs.
|
||||
*/
|
||||
bool HasHeaderIe(void) const { return FindHeaderIeIndex() != kInvalidIndex; }
|
||||
bool HasAnyHeaderIe(void) const { return FindHeaderIeIndex() != kInvalidIndex; }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the Header IE.
|
||||
* Finds a specific Information Element (IE) in the frame.
|
||||
*
|
||||
* @param[in] aIeId The Element Id of the Header IE.
|
||||
* This method searches the frame for a Header IE matching the Element ID of @p IeType and also validates that
|
||||
* the content of the IE is well-formed according to @p IeType.
|
||||
*
|
||||
* @returns A pointer to the Header IE, `nullptr` if not found.
|
||||
* @tparam IeType The IE subclass type to find.
|
||||
*
|
||||
* @returns A pointer to the IE, or `nullptr` if not found or if the IE content is malformed.
|
||||
*/
|
||||
uint8_t *GetHeaderIe(uint8_t aIeId) { return AsNonConst(AsConst(this)->GetHeaderIe(aIeId)); }
|
||||
template <typename IeType> const IeType *Find(void) const
|
||||
{
|
||||
return static_cast<const IeType *>(FindHeaderIe(HeaderIe::ValidateAs<IeType>));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the Header IE.
|
||||
* Finds a specific Information Element (IE) in the frame.
|
||||
*
|
||||
* @param[in] aIeId The Element Id of the Header IE.
|
||||
* This method searches the frame for a Header IE matching the Element ID of @p IeType and also validates that
|
||||
* the content of the IE is well-formed according to @p IeType.
|
||||
*
|
||||
* @returns A pointer to the Header IE, `nullptr` if not found.
|
||||
* @tparam IeType The IE subclass type to find.
|
||||
*
|
||||
* @returns A pointer to the IE, or `nullptr` if not found or if the IE content is malformed.
|
||||
*/
|
||||
const uint8_t *GetHeaderIe(uint8_t aIeId) const;
|
||||
template <typename IeType> IeType *Find(void) { return AsNonConst(AsConst(this)->Find<IeType>()); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to a specific Thread IE.
|
||||
* Indicates whether or not the frame contains a specific Information Element (IE).
|
||||
*
|
||||
* A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`.
|
||||
* This method checks whether the frame contains a Header IE matching the Element ID of @p IeType with valid
|
||||
* content according to @p IeType.
|
||||
*
|
||||
* @param[in] aSubType The sub type of the Thread IE.
|
||||
* @tparam IeType The IE subclass type to check.
|
||||
*
|
||||
* @returns A pointer to the Thread IE, `nullptr` if not found.
|
||||
* @retval TRUE The frame contains a valid instance of the IE.
|
||||
* @retval FALSE The frame does not contain the IE or its content is malformed.
|
||||
*/
|
||||
uint8_t *GetThreadIe(uint8_t aSubType) { return AsNonConst(AsConst(this)->GetThreadIe(aSubType)); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to a specific Thread IE.
|
||||
*
|
||||
* A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`.
|
||||
*
|
||||
* @param[in] aSubType The sub type of the Thread IE.
|
||||
*
|
||||
* @returns A pointer to the Thread IE, `nullptr` if not found.
|
||||
*/
|
||||
const uint8_t *GetThreadIe(uint8_t aSubType) const;
|
||||
template <typename IeType> bool Has(void) const { return Find<IeType>() != nullptr; }
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
/**
|
||||
* Finds CSL IE in the frame and modify its content.
|
||||
* Updates CSL IE content in the frame.
|
||||
*
|
||||
* @param[in] aCslPeriod CSL Period in CSL IE.
|
||||
* @param[in] aCslPhase CSL Phase in CSL IE.
|
||||
*/
|
||||
void SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the frame contains CSL IE.
|
||||
*
|
||||
* @retval TRUE If the frame contains CSL IE.
|
||||
* @retval FALSE If the frame doesn't contain CSL IE.
|
||||
*/
|
||||
bool HasCslIe(void) const;
|
||||
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
/**
|
||||
* Returns a pointer to a CSL IE.
|
||||
*
|
||||
* @returns A pointer to the CSL IE, `nullptr` if not found.
|
||||
*/
|
||||
const CslIe *GetCslIe(void) const;
|
||||
|
||||
/**
|
||||
* Returns a pointer to a CSL IE.
|
||||
*
|
||||
* @returns A pointer to the CSL IE, `nullptr` if not found.
|
||||
*/
|
||||
CslIe *GetCslIe(void) { return AsNonConst(AsConst(this)->GetCslIe()); }
|
||||
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
void UpdateCslIe(uint16_t aCslPeriod, uint16_t aCslPhase);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
/**
|
||||
* Finds Enhanced ACK Probing (Vendor Specific) IE and set its value.
|
||||
* Finds Enhanced ACK Probing (Vendor Specific) IE and updates its Link Metrics Data content.
|
||||
*
|
||||
* @param[in] aValue A pointer to the value to set.
|
||||
* @param[in] aLen The length of @p aValue.
|
||||
* @param[in] aData A pointer to the data to write.
|
||||
* @param[in] aLen The length of @p aData.
|
||||
*/
|
||||
void SetEnhAckProbingIe(const uint8_t *aValue, uint8_t aLen);
|
||||
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
void UpdateEnhAckProbingIe(const uint8_t *aData, uint8_t aLen);
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
|
||||
@@ -936,6 +852,14 @@ protected:
|
||||
static uint8_t CalculateSecurityHeaderSize(uint8_t aSecurityControl);
|
||||
static uint8_t CalculateKeySourceSize(uint8_t aSecurityControl);
|
||||
static uint8_t CalculateMicSize(uint8_t aSecurityControl);
|
||||
|
||||
private:
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
typedef bool (&HeaderIeMatcher)(const HeaderIe &aHeaderIe);
|
||||
|
||||
const HeaderIe *FindHeaderIe(HeaderIeMatcher aMatcher) const;
|
||||
HeaderIe *FindHeaderIe(HeaderIeMatcher aMatcher) { return AsNonConst(AsConst(this)->FindHeaderIe(aMatcher)); }
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1034,25 +958,6 @@ public:
|
||||
* @retval kErrorSecurity Received frame MIC check failed.
|
||||
*/
|
||||
Error ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const KeyMaterial &aMacKey);
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
/**
|
||||
* Gets the offset to network time.
|
||||
*
|
||||
* @returns The offset to network time.
|
||||
*/
|
||||
int64_t ComputeNetworkTimeOffset(void) const
|
||||
{
|
||||
return static_cast<int64_t>(GetTimeIe()->GetTime() - GetTimestamp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time sync sequence.
|
||||
*
|
||||
* @returns The time sync sequence.
|
||||
*/
|
||||
uint8_t ReadTimeSyncSeq(void) const { return GetTimeIe()->GetSequence(); }
|
||||
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,16 +44,17 @@ void HeaderIe::Init(uint8_t aId, uint8_t aLen)
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
|
||||
Error ConnectionIe::SetWakeupId(WakeupId aWakeupId)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
const HeaderIe *headerIe = GetHeaderIe();
|
||||
uint8_t wakeupIdLength = GetWakeupIdLength(aWakeupId);
|
||||
Error error = kErrorNone;
|
||||
uint8_t wakeupIdLength = GetWakeupIdLength(aWakeupId);
|
||||
|
||||
VerifyOrExit(GetSize() >= sizeof(ConnectionIe), error = kErrorParse);
|
||||
VerifyOrExit(GetSize() - sizeof(ConnectionIe) == wakeupIdLength, error = kErrorParse);
|
||||
|
||||
VerifyOrExit(headerIe->GetLength() > sizeof(ConnectionIe), error = kErrorParse);
|
||||
VerifyOrExit(headerIe->GetLength() - sizeof(ConnectionIe) == wakeupIdLength, error = kErrorParse);
|
||||
aWakeupId = LittleEndian::HostSwap64(aWakeupId);
|
||||
memcpy(GetWakeupIdData(), reinterpret_cast<uint8_t *>(&aWakeupId), wakeupIdLength);
|
||||
memcpy(GetBytes() + sizeof(ConnectionIe), reinterpret_cast<uint8_t *>(&aWakeupId), wakeupIdLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -61,22 +62,22 @@ exit:
|
||||
|
||||
Error ConnectionIe::GetWakeupId(WakeupId &aWakeupId) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
const HeaderIe *headerIe = GetHeaderIe();
|
||||
uint8_t wakeupIdLength;
|
||||
Error error = kErrorNone;
|
||||
uint8_t wakeupIdLength;
|
||||
|
||||
VerifyOrExit(headerIe->GetLength() > sizeof(ConnectionIe), error = kErrorParse);
|
||||
VerifyOrExit(GetSize() > sizeof(ConnectionIe), error = kErrorParse);
|
||||
|
||||
wakeupIdLength = headerIe->GetLength() - sizeof(ConnectionIe);
|
||||
wakeupIdLength = GetSize() - sizeof(ConnectionIe);
|
||||
VerifyOrExit(wakeupIdLength <= sizeof(WakeupId), error = kErrorParse);
|
||||
|
||||
aWakeupId = 0;
|
||||
memcpy(reinterpret_cast<uint8_t *>(&aWakeupId), GetWakeupIdData(), wakeupIdLength);
|
||||
memcpy(reinterpret_cast<uint8_t *>(&aWakeupId), GetBytes() + sizeof(ConnectionIe), wakeupIdLength);
|
||||
aWakeupId = LittleEndian::HostSwap64(aWakeupId);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
|
||||
} // namespace Mac
|
||||
|
||||
+188
-84
@@ -40,6 +40,7 @@
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/const_cast.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/num_utils.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
|
||||
@@ -59,14 +60,6 @@ OT_TOOL_PACKED_BEGIN
|
||||
class HeaderIe
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes the Header IE with a given ID and Length.
|
||||
*
|
||||
* @param[in] aId The IE Element ID.
|
||||
* @param[in] aLen The IE content length.
|
||||
*/
|
||||
void Init(uint8_t aId, uint8_t aLen);
|
||||
|
||||
/**
|
||||
* Returns the IE Element ID.
|
||||
*
|
||||
@@ -104,6 +97,29 @@ public:
|
||||
*/
|
||||
uint8_t *GetContent(void) { return AsNonConst(AsConst(this)->GetContent()); }
|
||||
|
||||
/**
|
||||
* Validates whether a given Header IE matches a specific IE subclass.
|
||||
*
|
||||
* This method checks whether @p aIe matches the Element ID of @p IeType (`IeType::kId`) and also casts @p aIe
|
||||
* to @p IeType to validate its content structure via `IeType::IsValid()`.
|
||||
*
|
||||
* @tparam IeType The IE subclass type to validate against.
|
||||
*
|
||||
* @param[in] aIe The Header IE to validate.
|
||||
*
|
||||
* @retval TRUE @p aIe matches @p IeType and its content is well-formed.
|
||||
* @retval FALSE @p aIe does not match @p IeType or its content is malformed.
|
||||
*/
|
||||
template <typename IeType> static bool ValidateAs(const HeaderIe &aIe)
|
||||
{
|
||||
return (aIe.GetId() == IeType::kId) && static_cast<const IeType *>(&aIe)->IsValid();
|
||||
}
|
||||
|
||||
protected:
|
||||
void Init(uint8_t aId, uint8_t aLen);
|
||||
uint8_t *GetBytes(void) { return reinterpret_cast<uint8_t *>(this); }
|
||||
const uint8_t *GetBytes(void) const { return reinterpret_cast<const uint8_t *>(this); }
|
||||
|
||||
private:
|
||||
// IEEE 802.15.4 Header IE descriptor (2 bytes, little-endian):
|
||||
//
|
||||
@@ -117,20 +133,24 @@ private:
|
||||
void SetId(uint8_t aId) { mLenIdType = UpdateBitsLittleEndian<uint16_t, kIdMask>(mLenIdType, aId); }
|
||||
void SetLength(uint8_t aLength) { mLenIdType = UpdateBitsLittleEndian<uint16_t, kLenMask>(mLenIdType, aLength); }
|
||||
|
||||
const uint8_t *GetBytes(void) const { return reinterpret_cast<const uint8_t *>(this); }
|
||||
|
||||
uint16_t mLenIdType;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* Implements CSL IE data structure.
|
||||
* Represents a CSL IE.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class CslIe
|
||||
class CslIe : public HeaderIe
|
||||
{
|
||||
friend class HeaderIe;
|
||||
|
||||
public:
|
||||
static constexpr uint8_t kHeaderIeId = 0x1a;
|
||||
static constexpr uint8_t kIeContentSize = sizeof(uint16_t) * 2;
|
||||
static constexpr uint8_t kId = 0x1a; ///< The CSL IE Element ID.
|
||||
|
||||
/**
|
||||
* Initializes the CSL IE.
|
||||
*/
|
||||
void Init(void) { HeaderIe::Init(kId, sizeof(CslIe) - sizeof(HeaderIe)); }
|
||||
|
||||
/**
|
||||
* Returns the CSL Period.
|
||||
@@ -161,31 +181,40 @@ public:
|
||||
void SetPhase(uint16_t aPhase) { mPhase = LittleEndian::HostSwap16(aPhase); }
|
||||
|
||||
private:
|
||||
bool IsValid(void) const { return GetSize() >= sizeof(CslIe); }
|
||||
|
||||
uint16_t mPhase;
|
||||
uint16_t mPeriod;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* Implements Termination2 IE.
|
||||
*
|
||||
* Is empty for template specialization.
|
||||
*/
|
||||
class Termination2Ie
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kHeaderIeId = 0x7f;
|
||||
static constexpr uint8_t kIeContentSize = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements vendor specific Header IE generation and parsing.
|
||||
* Represents a Termination2 IE.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class VendorIeHeader
|
||||
class Termination2Ie : public HeaderIe
|
||||
{
|
||||
friend class HeaderIe;
|
||||
|
||||
public:
|
||||
static constexpr uint8_t kId = 0x7f; ///< The Termination2 IE Element ID.
|
||||
|
||||
/**
|
||||
* Initializes the Termination2 IE.
|
||||
*/
|
||||
void Init(void) { HeaderIe::Init(kId, sizeof(Termination2Ie) - sizeof(HeaderIe)); }
|
||||
|
||||
private:
|
||||
bool IsValid(void) const { return true; }
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* Represents a Vendor Header IE.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class VendorIe : public HeaderIe
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kHeaderIeId = 0x00;
|
||||
static constexpr uint8_t kIeContentSize = sizeof(uint8_t) * 4;
|
||||
static constexpr uint8_t kId = 0x00; ///< The Vendor Specific IE Element ID.
|
||||
|
||||
/**
|
||||
* Returns the Vendor OUI.
|
||||
@@ -194,13 +223,6 @@ public:
|
||||
*/
|
||||
uint32_t GetVendorOui(void) const { return LittleEndian::ReadUint24(mOui); }
|
||||
|
||||
/**
|
||||
* Sets the Vendor OUI.
|
||||
*
|
||||
* @param[in] aVendorOui A Vendor OUI.
|
||||
*/
|
||||
void SetVendorOui(uint32_t aVendorOui) { LittleEndian::WriteUint24(aVendorOui, mOui); }
|
||||
|
||||
/**
|
||||
* Returns the Vendor IE sub-type.
|
||||
*
|
||||
@@ -208,11 +230,8 @@ public:
|
||||
*/
|
||||
uint8_t GetSubType(void) const { return mSubType; }
|
||||
|
||||
/**
|
||||
* Sets the Vendor IE sub-type.
|
||||
*
|
||||
* @param[in] aSubType The Vendor IE sub-type.
|
||||
*/
|
||||
protected:
|
||||
void SetVendorOui(uint32_t aVendorOui) { LittleEndian::WriteUint24(aVendorOui, mOui); }
|
||||
void SetSubType(uint8_t aSubType) { mSubType = aSubType; }
|
||||
|
||||
private:
|
||||
@@ -224,24 +243,25 @@ private:
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
/**
|
||||
* Implements Time Header IE generation and parsing.
|
||||
* Represents a Time Header IE.
|
||||
*
|
||||
* This IE is not specified in the Thread specification and is a custom feature in OpenThread (using Vendor IE
|
||||
* with Nest OUI).
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class TimeIe : public VendorIeHeader
|
||||
class TimeIe : public VendorIe
|
||||
{
|
||||
public:
|
||||
static constexpr uint32_t kVendorOuiNest = 0x18b430;
|
||||
static constexpr uint8_t kVendorIeTime = 0x01;
|
||||
static constexpr uint8_t kHeaderIeId = VendorIeHeader::kHeaderIeId;
|
||||
static constexpr uint8_t kIeContentSize = VendorIeHeader::kIeContentSize + sizeof(uint8_t) + sizeof(uint64_t);
|
||||
friend class HeaderIe;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Initializes the time IE.
|
||||
* Initializes the Time IE.
|
||||
*/
|
||||
void Init(void)
|
||||
{
|
||||
HeaderIe::Init(kId, sizeof(TimeIe) - sizeof(HeaderIe));
|
||||
SetVendorOui(kVendorOuiNest);
|
||||
SetSubType(kVendorIeTime);
|
||||
SetSubType(kSubType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,22 +292,100 @@ public:
|
||||
*/
|
||||
void SetTime(uint64_t aTime) { mTime = LittleEndian::HostSwap64(aTime); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the start of Time IE specific data content (i.e., sequence field).
|
||||
*
|
||||
* @returns A pointer to the Time IE data content bytes.
|
||||
*/
|
||||
const uint8_t *GetData(void) const { return &mSequence; }
|
||||
|
||||
private:
|
||||
bool IsValid(void) const
|
||||
{
|
||||
return (GetSize() >= sizeof(TimeIe)) && (GetVendorOui() == kVendorOuiNest) && (GetSubType() == kSubType);
|
||||
}
|
||||
|
||||
static constexpr uint32_t kVendorOuiNest = 0x18b430;
|
||||
static constexpr uint8_t kSubType = 0x01;
|
||||
|
||||
uint8_t mSequence;
|
||||
uint64_t mTime;
|
||||
} OT_TOOL_PACKED_END;
|
||||
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
|
||||
class ThreadIe
|
||||
/**
|
||||
* Represents a Thread Vendor IE.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ThreadVendorIe : public VendorIe
|
||||
{
|
||||
protected:
|
||||
static constexpr uint32_t kVendorOuiThread = 0xeab89b;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* Represents a Link Metrics Probing IE (using in Enhanced Ack).
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class LinkMetricsProbingIe : public ThreadVendorIe
|
||||
{
|
||||
friend class HeaderIe;
|
||||
|
||||
public:
|
||||
static constexpr uint8_t kHeaderIeId = VendorIeHeader::kHeaderIeId;
|
||||
static constexpr uint8_t kIeContentSize = VendorIeHeader::kIeContentSize;
|
||||
static constexpr uint32_t kVendorOuiThreadCompanyId = 0xeab89b;
|
||||
static constexpr uint8_t kEnhAckProbingIe = 0x00;
|
||||
};
|
||||
/**
|
||||
* The maximum length of Link Metrics Data in bytes (Thread specification limits metrics to 2).
|
||||
*/
|
||||
static constexpr uint8_t kMaxMetricsDataLen = 2;
|
||||
|
||||
/**
|
||||
* Initializes the Link Metrics Probing IE.
|
||||
*
|
||||
* @param[in] aMetricsDataLen The requested length of Link Metrics Data. If greater than `kMaxMetricsDataLen`,
|
||||
* then `kMaxMetricsDataLen` is used instead.
|
||||
*/
|
||||
void Init(uint8_t aMetricsDataLen)
|
||||
{
|
||||
HeaderIe::Init(kId, sizeof(LinkMetricsProbingIe) - sizeof(HeaderIe) + Min(aMetricsDataLen, kMaxMetricsDataLen));
|
||||
SetVendorOui(kVendorOuiThread);
|
||||
SetSubType(kSubType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of Link Metrics Data in bytes.
|
||||
*
|
||||
* @returns The length of Link Metrics Data in bytes.
|
||||
*/
|
||||
uint8_t GetMetricsDataLen(void) const { return GetSize() - sizeof(LinkMetricsProbingIe); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the Link Metrics Data bytes.
|
||||
*
|
||||
* @returns A pointer to the Link Metrics Data bytes.
|
||||
*/
|
||||
const uint8_t *GetMetricsData(void) const { return GetBytes() + sizeof(LinkMetricsProbingIe); }
|
||||
|
||||
/**
|
||||
* Writes Link Metrics Data content from a given buffer.
|
||||
*
|
||||
* @param[in] aData A pointer to a buffer containing the data to write. The caller must ensure that at least
|
||||
* `GetMetricsDataLen()` bytes are available in @p aData.
|
||||
*/
|
||||
void WriteMetricsDataFrom(const uint8_t *aData)
|
||||
{
|
||||
memcpy(AsNonConst(GetMetricsData()), aData, GetMetricsDataLen());
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kSubType = 0x00;
|
||||
|
||||
bool IsValid(void) const
|
||||
{
|
||||
return (GetSize() >= sizeof(LinkMetricsProbingIe)) && (GetVendorOui() == kVendorOuiThread) &&
|
||||
(GetSubType() == kSubType);
|
||||
}
|
||||
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
/**
|
||||
* This class implements Rendezvous Time IE data structure.
|
||||
*
|
||||
@@ -296,11 +394,17 @@ public:
|
||||
* not included in this class.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class RendezvousTimeIe
|
||||
class RendezvousTimeIe : public HeaderIe
|
||||
{
|
||||
friend class HeaderIe;
|
||||
|
||||
public:
|
||||
static constexpr uint8_t kHeaderIeId = 0x1d;
|
||||
static constexpr uint8_t kIeContentSize = sizeof(uint16_t);
|
||||
static constexpr uint8_t kId = 0x1d; ///< The Rendezvous Time IE Element ID.
|
||||
|
||||
/**
|
||||
* Initializes the Rendezvous Time IE.
|
||||
*/
|
||||
void Init(void) { HeaderIe::Init(kId, sizeof(RendezvousTimeIe) - sizeof(HeaderIe)); }
|
||||
|
||||
/**
|
||||
* This method returns the Rendezvous Time.
|
||||
@@ -317,27 +421,32 @@ public:
|
||||
void SetRendezvousTime(uint16_t aRendezvousTime) { mRendezvousTime = LittleEndian::HostSwap16(aRendezvousTime); }
|
||||
|
||||
private:
|
||||
bool IsValid(void) const { return GetSize() >= sizeof(RendezvousTimeIe); }
|
||||
|
||||
uint16_t mRendezvousTime;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
|
||||
/**
|
||||
* Implements Connection IE data structure.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ConnectionIe : public VendorIeHeader
|
||||
class ConnectionIe : public ThreadVendorIe
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kHeaderIeId = ThreadIe::kHeaderIeId;
|
||||
static constexpr uint8_t kIeContentSize = ThreadIe::kIeContentSize + sizeof(uint8_t);
|
||||
static constexpr uint8_t kThreadIeSubtype = 0x01;
|
||||
friend class HeaderIe;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Initializes the Connection IE.
|
||||
*
|
||||
* @param[in] aWakeupIdLength The length of the Wakeup ID field in bytes.
|
||||
*/
|
||||
void Init(void)
|
||||
void Init(uint8_t aWakeupIdLength)
|
||||
{
|
||||
SetVendorOui(ThreadIe::kVendorOuiThreadCompanyId);
|
||||
SetSubType(kThreadIeSubtype);
|
||||
HeaderIe::Init(kId, sizeof(ConnectionIe) - sizeof(HeaderIe) + aWakeupIdLength);
|
||||
SetVendorOui(kVendorOuiThread);
|
||||
SetSubType(kSubType);
|
||||
mConnectionWindow = 0;
|
||||
}
|
||||
|
||||
@@ -398,25 +507,20 @@ public:
|
||||
*/
|
||||
Error GetWakeupId(WakeupId &aWakeupId) const;
|
||||
|
||||
/**
|
||||
* Gets the pointer to the HeaderIe of this ConnectionIe.
|
||||
*
|
||||
* @returns A pointer to the HeaderIe.
|
||||
*/
|
||||
const HeaderIe *GetHeaderIe(void) const
|
||||
private:
|
||||
static constexpr uint8_t kSubType = 0x01;
|
||||
|
||||
static constexpr uint8_t kRetryIntervalMask = 0x3 << 4;
|
||||
static constexpr uint8_t kRetryCountMask = 0xf << 0;
|
||||
|
||||
bool IsValid(void) const
|
||||
{
|
||||
return reinterpret_cast<const HeaderIe *>(reinterpret_cast<const uint8_t *>(this) - sizeof(HeaderIe));
|
||||
return (GetSize() >= sizeof(ConnectionIe)) && (GetVendorOui() == kVendorOuiThread) &&
|
||||
(GetSubType() == kSubType);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kRetryIntervalOffset = 4;
|
||||
static constexpr uint8_t kRetryIntervalMask = 0x3 << kRetryIntervalOffset;
|
||||
static constexpr uint8_t kRetryCountMask = 0xf;
|
||||
|
||||
const uint8_t *GetWakeupIdData(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
|
||||
uint8_t *GetWakeupIdData(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(*this); }
|
||||
|
||||
uint8_t mConnectionWindow;
|
||||
// Followed by variable length Wakeup ID
|
||||
} OT_TOOL_PACKED_END;
|
||||
#endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
|
||||
|
||||
@@ -413,7 +413,7 @@ void SubMac::ProcessTransmitSecurity(void)
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
// Transmit security will be processed after time IE content is updated.
|
||||
VerifyOrExit(mTransmitFrame.GetTimeIeOffset() == 0);
|
||||
VerifyOrExit(!mTransmitFrame.Has<TimeIe>());
|
||||
#endif
|
||||
|
||||
mTransmitFrame.ProcessTransmitAesCcm(*extAddress);
|
||||
@@ -606,7 +606,7 @@ void SubMac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aErro
|
||||
aFrame.SetIsARetransmission(true);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_MAC_SOFTWARE_RETX_SECURITY_ENABLE
|
||||
if (aFrame.GetSecurityEnabled() && aFrame.IsSecurityProcessed() && aFrame.HasHeaderIe())
|
||||
if (aFrame.GetSecurityEnabled() && aFrame.IsSecurityProcessed() && aFrame.HasAnyHeaderIe())
|
||||
{
|
||||
aFrame.DecryptTransmitAesCcm(GetExtAddress());
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ void SubMac::UpdateCslLastSyncTimestamp(TxFrame &aFrame, RxFrame *aAckFrame)
|
||||
{
|
||||
// Actual synchronization timestamp should be from the sent frame instead of the current time.
|
||||
// Assuming the error here since it is bounded and has very small effect on the final window duration.
|
||||
if (aAckFrame != nullptr && aFrame.HasCslIe())
|
||||
if (aAckFrame != nullptr && aFrame.Has<CslIe>())
|
||||
{
|
||||
mCslLastSync = TimeMicro(GetLocalTime());
|
||||
}
|
||||
|
||||
@@ -112,9 +112,9 @@ Mac::TxFrame *WakeupTxScheduler::PrepareWakeupFrame(Mac::TxFrames &aTxFrames)
|
||||
rendezvousTimeUs = mIntervalUs;
|
||||
rendezvousTimeUs += (mIntervalUs - (kWakeupFrameLength + kParentRequestLength) * kOctetDuration) / 2;
|
||||
|
||||
frame->GetRendezvousTimeIe()->SetRendezvousTime(ClampToUint16(rendezvousTimeUs / kUsPerTenSymbols));
|
||||
frame->Find<Mac::RendezvousTimeIe>()->SetRendezvousTime(ClampToUint16(rendezvousTimeUs / kUsPerTenSymbols));
|
||||
|
||||
connectionIe = frame->GetConnectionIe();
|
||||
connectionIe = frame->Find<Mac::ConnectionIe>();
|
||||
connectionIe->SetRetryInterval(kConnectionRetryInterval);
|
||||
connectionIe->SetRetryCount(kConnectionRetryCount);
|
||||
|
||||
|
||||
@@ -766,7 +766,7 @@ Neighbor *MeshForwarder::UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame,
|
||||
#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
if (aFrame.HasCslIe() && aIsDataPoll)
|
||||
if (aFrame.Has<Mac::CslIe>() && aIsDataPoll)
|
||||
{
|
||||
failLimit = kFailedCslDataPollTransmissions;
|
||||
}
|
||||
|
||||
@@ -59,13 +59,19 @@ void ThreadLinkInfo::SetFrom(const Mac::RxFrame &aFrame)
|
||||
mChannel = aFrame.GetChannel();
|
||||
mRss = aFrame.GetRssi();
|
||||
mLqi = aFrame.GetLqi();
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
if (aFrame.GetTimeIe() != nullptr)
|
||||
{
|
||||
mNetworkTimeOffset = aFrame.ComputeNetworkTimeOffset();
|
||||
mTimeSyncSeq = aFrame.ReadTimeSyncSeq();
|
||||
const Mac::TimeIe *timeIe = aFrame.Find<Mac::TimeIe>();
|
||||
|
||||
if (timeIe != nullptr)
|
||||
{
|
||||
mNetworkTimeOffset = static_cast<int64_t>(timeIe->GetTime() - aFrame.GetTimestamp());
|
||||
mTimeSyncSeq = timeIe->GetSequence();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
mRadioType = static_cast<uint8_t>(aFrame.GetRadioType());
|
||||
#endif
|
||||
|
||||
@@ -761,7 +761,7 @@ void TestMacFrameAckGeneration(void)
|
||||
|
||||
SuccessOrQuit(ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data)));
|
||||
|
||||
csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
|
||||
csl = ackFrame.Find<Mac::CslIe>();
|
||||
VerifyOrQuit(ackFrame.mLength == 25);
|
||||
VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kTypeAck);
|
||||
VerifyOrQuit(ackFrame.GetSecurityEnabled());
|
||||
@@ -775,8 +775,8 @@ void TestMacFrameAckGeneration(void)
|
||||
VerifyOrQuit(csl->GetPeriod() == 3125 && csl->GetPhase() == 3105);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
ackFrame.SetCslIe(123, 456);
|
||||
csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
|
||||
ackFrame.UpdateCslIe(123, 456);
|
||||
csl = ackFrame.Find<Mac::CslIe>();
|
||||
VerifyOrQuit(csl->GetPeriod() == 123 && csl->GetPhase() == 456);
|
||||
#endif
|
||||
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
||||
@@ -860,8 +860,8 @@ void TestMacWakeupFrameGeneration(void)
|
||||
// Validate that the frame satisfies the wake-up frame definition
|
||||
VerifyOrQuit(txFrame.GetType() == Mac::Frame::kTypeMultipurpose);
|
||||
VerifyOrQuit(!txFrame.GetAckRequest());
|
||||
VerifyOrQuit(txFrame.GetRendezvousTimeIe() != nullptr);
|
||||
VerifyOrQuit(txFrame.GetConnectionIe() != nullptr);
|
||||
VerifyOrQuit(txFrame.Has<Mac::RendezvousTimeIe>());
|
||||
VerifyOrQuit(txFrame.Has<Mac::ConnectionIe>());
|
||||
VerifyOrQuit(txFrame.GetPayloadLength() == 0);
|
||||
SuccessOrQuit(txFrame.GetSrcAddr(addr));
|
||||
VerifyOrQuit(CompareAddresses(src, addr));
|
||||
@@ -872,13 +872,13 @@ void TestMacWakeupFrameGeneration(void)
|
||||
txFrame.SetFrameCounter(0xfcfcfcfc);
|
||||
txFrame.SetKeySource(kKeySource);
|
||||
txFrame.SetKeyId(0x1d);
|
||||
txFrame.GetRendezvousTimeIe()->SetRendezvousTime(0xabcd);
|
||||
connectionIe = txFrame.GetConnectionIe();
|
||||
txFrame.Find<Mac::RendezvousTimeIe>()->SetRendezvousTime(0xabcd);
|
||||
connectionIe = txFrame.Find<Mac::ConnectionIe>();
|
||||
connectionIe->SetRetryInterval(1);
|
||||
connectionIe->SetRetryCount(12);
|
||||
VerifyOrQuit(connectionIe->SetWakeupId(kWakeupId) == kErrorParse);
|
||||
|
||||
VerifyOrQuit(txFrame.GetRendezvousTimeIe()->GetRendezvousTime() == 0xabcd);
|
||||
VerifyOrQuit(txFrame.Find<Mac::RendezvousTimeIe>()->GetRendezvousTime() == 0xabcd);
|
||||
VerifyOrQuit(connectionIe->GetRetryInterval() == 1);
|
||||
VerifyOrQuit(connectionIe->GetRetryCount() == 12);
|
||||
VerifyOrQuit(connectionIe->GetWakeupId(wakeupId) == kErrorParse);
|
||||
@@ -905,8 +905,8 @@ void TestMacWakeupFrameGeneration(void)
|
||||
// Validate that the frame satisfies the wake-up frame definition
|
||||
VerifyOrQuit(txFrame.GetType() == Mac::Frame::kTypeMultipurpose);
|
||||
VerifyOrQuit(!txFrame.GetAckRequest());
|
||||
VerifyOrQuit(txFrame.GetRendezvousTimeIe() != nullptr);
|
||||
VerifyOrQuit(txFrame.GetConnectionIe() != nullptr);
|
||||
VerifyOrQuit(txFrame.Has<Mac::RendezvousTimeIe>());
|
||||
VerifyOrQuit(txFrame.Has<Mac::ConnectionIe>());
|
||||
VerifyOrQuit(txFrame.GetPayloadLength() == 0);
|
||||
SuccessOrQuit(txFrame.GetSrcAddr(addr));
|
||||
VerifyOrQuit(CompareAddresses(src, addr));
|
||||
@@ -917,13 +917,13 @@ void TestMacWakeupFrameGeneration(void)
|
||||
txFrame.SetFrameCounter(0xfcfcfcfc);
|
||||
txFrame.SetKeySource(kKeySource);
|
||||
txFrame.SetKeyId(0x1d);
|
||||
txFrame.GetRendezvousTimeIe()->SetRendezvousTime(0xabcd);
|
||||
connectionIe = txFrame.GetConnectionIe();
|
||||
txFrame.Find<Mac::RendezvousTimeIe>()->SetRendezvousTime(0xabcd);
|
||||
connectionIe = txFrame.Find<Mac::ConnectionIe>();
|
||||
connectionIe->SetRetryInterval(1);
|
||||
connectionIe->SetRetryCount(12);
|
||||
SuccessOrQuit(connectionIe->SetWakeupId(kWakeupId));
|
||||
|
||||
VerifyOrQuit(txFrame.GetRendezvousTimeIe()->GetRendezvousTime() == 0xabcd);
|
||||
VerifyOrQuit(txFrame.Find<Mac::RendezvousTimeIe>()->GetRendezvousTime() == 0xabcd);
|
||||
VerifyOrQuit(connectionIe->GetRetryInterval() == 1);
|
||||
VerifyOrQuit(connectionIe->GetRetryCount() == 12);
|
||||
SuccessOrQuit(connectionIe->GetWakeupId(wakeupId));
|
||||
|
||||
Reference in New Issue
Block a user