[mac] adds the wake-up identifier to the Connection IE (#11907)

The P2P peer can be woken up using the wake-up identifier. The wake-up identifier
is included in the Connection IE. This commit implements methods to the Connection IE
and Frame to process wake-up identifier.
This commit is contained in:
Zhanglong Xia
2025-10-28 11:01:19 -07:00
committed by GitHub
parent ce17d9e6a9
commit 4cced2e81e
8 changed files with 238 additions and 23 deletions
+27 -12
View File
@@ -299,11 +299,12 @@ exit:
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
bool Frame::IsWakeupFrame(void) const
{
const uint16_t fcf = GetFrameControlField();
bool result = false;
uint8_t keyIdMode;
uint8_t firstIeIndex;
Address srcAddress;
const uint16_t fcf = GetFrameControlField();
bool result = false;
uint8_t keyIdMode;
uint8_t firstIeIndex;
Address srcAddress;
const ConnectionIe *connectionIe;
// Wake-up frame is a Multipurpose frame without Ack Request...
VerifyOrExit((fcf & kFcfFrameTypeMask) == kTypeMultipurpose);
@@ -319,12 +320,12 @@ bool Frame::IsWakeupFrame(void) const
// ... that has Rendezvous Time IE and Connection IE...
VerifyOrExit(GetRendezvousTimeIe() != nullptr);
VerifyOrExit(GetConnectionIe() != nullptr);
VerifyOrExit((connectionIe = GetConnectionIe()) != nullptr);
// ... but no other IEs nor payload.
firstIeIndex = FindHeaderIeIndex();
VerifyOrExit(mPsdu + firstIeIndex + sizeof(HeaderIe) + RendezvousTimeIe::kIeContentSize + sizeof(HeaderIe) +
ConnectionIe::kIeContentSize ==
connectionIe->GetHeaderIe()->GetLength() ==
GetFooter());
result = true;
@@ -1505,26 +1506,39 @@ exit:
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
Error TxFrame::GenerateWakeupFrame(PanId aPanId, const Address &aDest, const Address &aSource)
Error TxFrame::GenerateWakeupFrame(PanId aPanId, const WakeupRequest &aWakeupRequest, const Address &aSource)
{
Error error = kErrorNone;
uint16_t fcf;
uint8_t secCtl;
uint8_t wakeupIdLength;
FrameBuilder builder;
Address dest;
fcf = kTypeMultipurpose | kMpFcfLongFrame | kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression |
kMpFcfIePresent;
VerifyOrExit(!aDest.IsNone() && !aSource.IsNone(), error = kErrorInvalidArgs);
VerifyOrExit(!aSource.IsNone(), error = kErrorInvalidArgs);
fcf |= DetermineFcfAddrType(aDest, kMpFcfDstAddrShift);
if (aWakeupRequest.IsWakeupByExtAddress())
{
wakeupIdLength = 0;
dest.SetExtended(aWakeupRequest.GetExtAddress());
}
else
{
wakeupIdLength = GetWakeupIdLength(aWakeupRequest.GetWakeupId());
dest.SetNone();
}
fcf |= DetermineFcfAddrType(dest, kMpFcfDstAddrShift);
fcf |= DetermineFcfAddrType(aSource, kMpFcfSrcAddrShift);
builder.Init(mPsdu, GetMtu());
IgnoreError(builder.AppendLittleEndianUint16(fcf));
IgnoreError(builder.AppendLittleEndianUint16(aPanId));
IgnoreError(builder.AppendMacAddress(aDest));
IgnoreError(builder.AppendMacAddress(dest));
IgnoreError(builder.AppendMacAddress(aSource));
secCtl = kKeyIdMode2 | kSecurityEncMic32;
@@ -1534,8 +1548,9 @@ Error TxFrame::GenerateWakeupFrame(PanId aPanId, const Address &aDest, const Add
builder.Append<HeaderIe>()->Init(RendezvousTimeIe::kHeaderIeId, sizeof(RendezvousTimeIe));
builder.Append<RendezvousTimeIe>();
builder.Append<HeaderIe>()->Init(ConnectionIe::kHeaderIeId, sizeof(ConnectionIe));
builder.Append<HeaderIe>()->Init(ConnectionIe::kHeaderIeId, sizeof(ConnectionIe) + wakeupIdLength);
builder.Append<ConnectionIe>()->Init();
builder.AppendLength(wakeupIdLength);
builder.AppendLength(CalculateMicSize(secCtl) + GetFcsSize());
+4 -4
View File
@@ -1322,14 +1322,14 @@ public:
/**
* Generate IEE 802.15.4 Wake-up frame.
*
* @param[in] aPanId A destination PAN identifier
* @param[in] aDest A destination address (short or extended)
* @param[in] aSource A source address (short or extended)
* @param[in] aPanId A destination PAN identifier
* @param[in] aWakeupRequest A const reference to the wake-up request.
* @param[in] aSource A source address (short or extended)
*
* @retval kErrorNone Successfully generated Wake-up frame.
* @retval kErrorInvalidArgs @p aDest or @p aSource have incorrect type.
*/
Error GenerateWakeupFrame(PanId aPanId, const Address &aDest, const Address &aSource);
Error GenerateWakeupFrame(PanId aPanId, const WakeupRequest &aWakeupRequest, const Address &aSource);
#endif
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
+36
View File
@@ -43,5 +43,41 @@ void HeaderIe::Init(uint16_t aId, uint8_t aLen)
SetLength(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);
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);
exit:
return error;
}
Error ConnectionIe::GetWakeupId(WakeupId &aWakeupId) const
{
Error error = kErrorNone;
const HeaderIe *headerIe = GetHeaderIe();
uint8_t wakeupIdLength;
VerifyOrExit(headerIe->GetLength() > sizeof(ConnectionIe), error = kErrorParse);
wakeupIdLength = headerIe->GetLength() - sizeof(ConnectionIe);
VerifyOrExit(wakeupIdLength <= sizeof(WakeupId), error = kErrorParse);
aWakeupId = 0;
memcpy(reinterpret_cast<uint8_t *>(&aWakeupId), GetWakeupIdData(), wakeupIdLength);
aWakeupId = LittleEndian::HostSwap64(aWakeupId);
exit:
return error;
}
#endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
} // namespace Mac
} // namespace ot
+33
View File
@@ -377,11 +377,44 @@ public:
*/
void SetRetryCount(uint8_t aRetryCount) { WriteBits<uint8_t, kRetryCountMask>(mConnectionWindow, aRetryCount); }
/**
* Sets the Wake-up Identifier.
*
* @param[in] aWakeupId The Wake-up Identifier.
*
* @retval kErrorNone Successfully set the Wake-up Identifier.
* @retval kErrorParse The length of the given Wake-up Identifier didn't match the reserved length.
*/
Error SetWakeupId(WakeupId aWakeupId);
/**
* Gets the Wake-up Identifier.
*
* @param[out] aWakeupId A reference to the Wake-up Identifier.
*
* @retval kErrorNone Successfully got the Wake-up Identifier.
* @retval kErrorParse Failed to parse the Wake-up Identifier from the Connection IE.
*/
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
{
return reinterpret_cast<const HeaderIe *>(reinterpret_cast<const uint8_t *>(this) - sizeof(HeaderIe));
}
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;
} OT_TOOL_PACKED_END;
#endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
+22
View File
@@ -35,6 +35,7 @@
#include <stdio.h>
#include "common/bit_utils.hpp"
#include "common/code_utils.hpp"
#include "common/random.hpp"
#include "common/string.hpp"
@@ -404,6 +405,27 @@ bool KeyMaterial::operator==(const KeyMaterial &aOther) const
#endif
}
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
uint8_t GetWakeupIdLength(WakeupId aWakeupId)
{
uint8_t zeroBytesCount = 0;
for (int i = static_cast<int>(sizeof(WakeupId)) - 1; i >= 1; --i)
{
if (((aWakeupId >> (i * kBitsPerByte)) & 0xFF) == 0)
{
zeroBytesCount++;
}
else
{
break;
}
}
return sizeof(WakeupId) - zeroBytesCount;
}
#endif
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
void WakeupRequest::SetExtAddress(const ExtAddress &aExtAddress)
{
+40
View File
@@ -81,6 +81,11 @@ typedef otShortAddress ShortAddress;
constexpr ShortAddress kShortAddrBroadcast = OT_RADIO_BROADCAST_SHORT_ADDR; ///< Broadcast Short Address.
constexpr ShortAddress kShortAddrInvalid = OT_RADIO_INVALID_SHORT_ADDR; ///< Invalid Short Address.
/**
* Represents the wake-up identifier.
*/
typedef otWakeupId WakeupId;
/**
* Generates a random IEEE 802.15.4 PAN ID.
*
@@ -960,6 +965,19 @@ private:
uint8_t mUncertainty;
};
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
/**
* Gets the length of the wake-up identifier.
*
* The length is the number of bytes remaining after removing the most significant zero bytes.
*
* @param[in] aWakeupId The wake-up identifier.
*
* @returns The length of the @p aWakeupId.
*/
uint8_t GetWakeupIdLength(WakeupId aWakeupId);
#endif
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
/**
* Represents a wake-up request.
@@ -1004,6 +1022,28 @@ public:
*/
ExtAddress &GetExtAddress(void);
/**
* Gets the Wake-up Identifier of the wake-up request.
*
* MUST be used only if the wake-up request type is `kTypeWakeupId` or `kTypeGroupWakeupId`.
*
* @returns The Wake-up Identifier.
*/
WakeupId GetWakeupId(void) const { return mShared.mWakeupId; }
/**
* Sets the wake-up request with the Wake-up Identifier.
*
* The type is also updated to indicate that the wake-up request type is `kTypeWakeupId`.
*
* @param[in] aWakeupId A Wake-up Identifier.
*/
void SetWakeupId(WakeupId aWakeupId)
{
SetType(kTypeWakeupId);
mShared.mWakeupId = aWakeupId;
}
/**
* Sets the wake-up request type.
*
+2 -3
View File
@@ -80,7 +80,6 @@ void WakeupTxScheduler::RequestWakeupFrameTransmission(void) { Get<Mac::Mac>().R
Mac::TxFrame *WakeupTxScheduler::PrepareWakeupFrame(Mac::TxFrames &aTxFrames)
{
Mac::TxFrame *frame = nullptr;
Mac::Address target;
Mac::Address source;
uint32_t radioTxDelay;
uint32_t rendezvousTimeUs;
@@ -89,7 +88,6 @@ Mac::TxFrame *WakeupTxScheduler::PrepareWakeupFrame(Mac::TxFrames &aTxFrames)
VerifyOrExit(mIsRunning);
target.SetExtended(mWakeupRequest.GetExtAddress());
source.SetExtended(Get<Mac::Mac>().GetExtAddress());
VerifyOrExit(mTxTimeUs >= nowUs);
radioTxDelay = mTxTimeUs - nowUs;
@@ -100,7 +98,8 @@ Mac::TxFrame *WakeupTxScheduler::PrepareWakeupFrame(Mac::TxFrames &aTxFrames)
frame = &aTxFrames.GetTxFrame();
#endif
VerifyOrExit(frame->GenerateWakeupFrame(Get<Mac::Mac>().GetPanId(), target, source) == kErrorNone, frame = nullptr);
VerifyOrExit(frame->GenerateWakeupFrame(Get<Mac::Mac>().GetPanId(), mWakeupRequest, source) == kErrorNone,
frame = nullptr);
frame->SetTxDelayBaseTime(static_cast<uint32_t>(Get<Radio>().GetNow()));
frame->SetTxDelay(radioTxDelay);
frame->SetCsmaCaEnabled(kWakeupFrameTxCca);