diff --git a/examples/platforms/utils/mac_frame.cpp b/examples/platforms/utils/mac_frame.cpp index cde7a4f81..20ff613ff 100644 --- a/examples/platforms/utils/mac_frame.cpp +++ b/examples/platforms/utils/mac_frame.cpp @@ -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(aFrame)->SetCslIe(aCslPeriod, aCslPhase); + static_cast(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(aDest)->Init(Mac::CslIe::kHeaderIeId, sizeof(Mac::CslIe)); + reinterpret_cast(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(aDest); assert(aDest != nullptr); - reinterpret_cast(aDest)->Init(Mac::ThreadIe::kHeaderIeId, len); - - aDest += sizeof(Mac::HeaderIe); - - reinterpret_cast(aDest)->SetVendorOui(Mac::ThreadIe::kVendorOuiThreadCompanyId); - reinterpret_cast(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(aFrame)->SetEnhAckProbingIe(aData, aDataLen); + reinterpret_cast(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(aFrame)->HasCslIe()) // CSL IE should be filled for every transmit attempt + if (static_cast(aFrame)->Has()) // CSL IE should be filled for every transmit attempt { otMacFrameSetCslIe(aFrame, aRadioContext->mCslPeriod, ComputeCslPhase(aRadioTime, aRadioContext)); } diff --git a/src/core/mac/data_poll_sender.cpp b/src/core/mac/data_poll_sender.cpp index 3595eb314..e4ec52a55 100644 --- a/src/core/mac/data_poll_sender.cpp +++ b/src/core/mac/data_poll_sender.cpp @@ -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() ? 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()) { // 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().PrepareMacHeaders(*frame, frameInfo, nullptr); #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - if (frame->HasCslIe()) + if (frame->Has()) { // Disable frame retransmission when the data poll has CSL IE included aTxFrames.SetMaxFrameRetries(0); diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index c728e7acf..2695588d1 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -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()); #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(); - frame->SetTimeIeOffset(timeIeOffset); - - if (timeIeOffset != 0) + if (timeIe == nullptr) { + frame->SetTimeIeOffset(0); + } + else + { + uint8_t offset = static_cast(timeIe->GetData() - frame->GetPsdu()); + + frame->SetTimeIeOffset(offset); frame->SetTimeSyncSeq(Get().GetTimeSyncSeq()); frame->SetNetworkTimeOffset(Get().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()) { Get().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(aFrame.GetTimeIe()); - VerifyOrExit(cur != nullptr); - - cur += sizeof(VendorIeHeader); - offset = static_cast(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(); 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(); + uint8_t dataLen; - const HeaderIe *enhAckProbingIe = - reinterpret_cast(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().ProcessEnhAckIeData(probingIe->GetMetricsData(), dataLen, aNeighbor); - Get().ProcessEnhAckIeData(reinterpret_cast(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(); 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()->GetRendezvousTime() * kUsPerTenSymbols; rvTimestampUs = aFrame.GetTimestamp() + kRadioHeaderPhrDuration + aFrame.GetLength() * kOctetDuration + rvTimeUs; if (rvTimestampUs > radioNowUs + kCslRequestAhead) diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index c9f8ae46b..97b8f9222 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -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 diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp index f29536c9b..61d268ba5 100644 --- a/src/core/mac/mac_frame.cpp +++ b/src/core/mac/mac_frame.cpp @@ -223,7 +223,6 @@ void TxFrame::Info::PrepareHeadersIn(TxFrame &aTxFrame) const #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE if (mAppendTimeIe) { - builder.Append()->Init(TimeIe::kHeaderIeId, sizeof(TimeIe)); builder.Append()->Init(); } #endif @@ -231,15 +230,14 @@ void TxFrame::Info::PrepareHeadersIn(TxFrame &aTxFrame) const #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE if (mAppendCslIe) { - builder.Append()->Init(CslIe::kHeaderIeId, sizeof(CslIe)); - builder.Append(); + builder.Append()->Init(); aTxFrame.SetCslIePresent(true); } #endif if ((fcf & kFcfIePresent) && ((mType == kTypeMacCmd) || !mEmptyPayload)) { - builder.Append()->Init(Termination2Ie::kHeaderIeId, Termination2Ie::kIeContentSize); + builder.Append()->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()); + VerifyOrExit((connectionIe = Find()) != 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(&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(&mPsdu[index]); - - if ((ie->GetId() == VendorIeHeader::kHeaderIeId) && (ie->GetLength() >= VendorIeHeader::kIeContentSize)) - { - const VendorIeHeader *vendorIe = reinterpret_cast(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(); 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(cur)->GetLength() >= CslIe::kIeContentSize); - csl = reinterpret_cast(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(); - 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(&mPsdu[index]); - - if ((ie->GetId() == VendorIeHeader::kHeaderIeId) && (ie->GetLength() >= TimeIe::kIeContentSize)) - { - const TimeIe *vendorIe = reinterpret_cast(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()->Init(RendezvousTimeIe::kHeaderIeId, sizeof(RendezvousTimeIe)); - builder.Append(); + builder.Append()->Init(); - builder.Append()->Init(ConnectionIe::kHeaderIeId, sizeof(ConnectionIe) + wakeupIdLength); - builder.Append()->Init(); + builder.Append()->Init(wakeupIdLength); builder.AppendLength(wakeupIdLength); builder.AppendLength(CalculateMicSize(secCtl) + GetFcsSize()); diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp index e528b8ae2..d992dffb6 100644 --- a/src/core/mac/mac_frame.hpp +++ b/src/core/mac/mac_frame.hpp @@ -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(ie)->GetLength() >= RendezvousTimeIe::kIeContentSize) - ? reinterpret_cast(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(ie)->GetLength() >= ConnectionIe::kIeContentSize) - ? reinterpret_cast(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 const IeType *Find(void) const + { + return static_cast(FindHeaderIe(HeaderIe::ValidateAs)); + } /** - * 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 IeType *Find(void) { return AsNonConst(AsConst(this)->Find()); } /** - * 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 bool Has(void) const { return Find() != 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(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 }; /** diff --git a/src/core/mac/mac_header_ie.cpp b/src/core/mac/mac_header_ie.cpp index 825c99fdc..26959edc3 100644 --- a/src/core/mac/mac_header_ie.cpp +++ b/src/core/mac/mac_header_ie.cpp @@ -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(&aWakeupId), wakeupIdLength); + memcpy(GetBytes() + sizeof(ConnectionIe), reinterpret_cast(&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(&aWakeupId), GetWakeupIdData(), wakeupIdLength); + memcpy(reinterpret_cast(&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 diff --git a/src/core/mac/mac_header_ie.hpp b/src/core/mac/mac_header_ie.hpp index 62332a963..21c843ab3 100644 --- a/src/core/mac/mac_header_ie.hpp +++ b/src/core/mac/mac_header_ie.hpp @@ -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 static bool ValidateAs(const HeaderIe &aIe) + { + return (aIe.GetId() == IeType::kId) && static_cast(&aIe)->IsValid(); + } + +protected: + void Init(uint8_t aId, uint8_t aLen); + uint8_t *GetBytes(void) { return reinterpret_cast(this); } + const uint8_t *GetBytes(void) const { return reinterpret_cast(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(mLenIdType, aId); } void SetLength(uint8_t aLength) { mLenIdType = UpdateBitsLittleEndian(mLenIdType, aLength); } - const uint8_t *GetBytes(void) const { return reinterpret_cast(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(reinterpret_cast(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(this) + sizeof(*this); } - uint8_t *GetWakeupIdData(void) { return reinterpret_cast(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 diff --git a/src/core/mac/sub_mac.cpp b/src/core/mac/sub_mac.cpp index 4669162d1..75f712cb6 100644 --- a/src/core/mac/sub_mac.cpp +++ b/src/core/mac/sub_mac.cpp @@ -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()); #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()); } diff --git a/src/core/mac/sub_mac_csl_receiver.cpp b/src/core/mac/sub_mac_csl_receiver.cpp index bec526301..1b15758ab 100644 --- a/src/core/mac/sub_mac_csl_receiver.cpp +++ b/src/core/mac/sub_mac_csl_receiver.cpp @@ -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()) { mCslLastSync = TimeMicro(GetLocalTime()); } diff --git a/src/core/mac/wakeup_tx_scheduler.cpp b/src/core/mac/wakeup_tx_scheduler.cpp index cb3967b9a..4ee3024f1 100644 --- a/src/core/mac/wakeup_tx_scheduler.cpp +++ b/src/core/mac/wakeup_tx_scheduler.cpp @@ -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()->SetRendezvousTime(ClampToUint16(rendezvousTimeUs / kUsPerTenSymbols)); - connectionIe = frame->GetConnectionIe(); + connectionIe = frame->Find(); connectionIe->SetRetryInterval(kConnectionRetryInterval); connectionIe->SetRetryCount(kConnectionRetryCount); diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index e2624fe71..574e8d1e3 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -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() && aIsDataPoll) { failLimit = kFailedCslDataPollTransmissions; } diff --git a/src/core/thread/thread_link_info.cpp b/src/core/thread/thread_link_info.cpp index 762a7a5dd..2e7ecd81d 100644 --- a/src/core/thread/thread_link_info.cpp +++ b/src/core/thread/thread_link_info.cpp @@ -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(); + + if (timeIe != nullptr) + { + mNetworkTimeOffset = static_cast(timeIe->GetTime() - aFrame.GetTimestamp()); + mTimeSyncSeq = timeIe->GetSequence(); + } } #endif + #if OPENTHREAD_CONFIG_MULTI_RADIO mRadioType = static_cast(aFrame.GetRadioType()); #endif diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp index d9bb83caa..90b2779f6 100644 --- a/tests/unit/test_mac_frame.cpp +++ b/tests/unit/test_mac_frame.cpp @@ -761,7 +761,7 @@ void TestMacFrameAckGeneration(void) SuccessOrQuit(ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data))); - csl = reinterpret_cast(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe)); + csl = ackFrame.Find(); 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(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe)); + ackFrame.UpdateCslIe(123, 456); + csl = ackFrame.Find(); 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()); + VerifyOrQuit(txFrame.Has()); 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()->SetRendezvousTime(0xabcd); + connectionIe = txFrame.Find(); connectionIe->SetRetryInterval(1); connectionIe->SetRetryCount(12); VerifyOrQuit(connectionIe->SetWakeupId(kWakeupId) == kErrorParse); - VerifyOrQuit(txFrame.GetRendezvousTimeIe()->GetRendezvousTime() == 0xabcd); + VerifyOrQuit(txFrame.Find()->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()); + VerifyOrQuit(txFrame.Has()); 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()->SetRendezvousTime(0xabcd); + connectionIe = txFrame.Find(); connectionIe->SetRetryInterval(1); connectionIe->SetRetryCount(12); SuccessOrQuit(connectionIe->SetWakeupId(kWakeupId)); - VerifyOrQuit(txFrame.GetRendezvousTimeIe()->GetRendezvousTime() == 0xabcd); + VerifyOrQuit(txFrame.Find()->GetRendezvousTime() == 0xabcd); VerifyOrQuit(connectionIe->GetRetryInterval() == 1); VerifyOrQuit(connectionIe->GetRetryCount() == 12); SuccessOrQuit(connectionIe->GetWakeupId(wakeupId));