mirror of
https://github.com/espressif/openthread.git
synced 2026-10-12 10:47:43 +00:00
[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:
+27
-12
@@ -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());
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user