mirror of
https://github.com/espressif/openthread.git
synced 2026-09-14 05:00:11 +00:00
[mac] multipurpose wake-up frame support (#10728)
1. Add OT_WAKEUP_COORDINATOR and OT_WAKEUP_END_DEVICE build options. 2. Add support for parsing and constructing 802.15.4 Multipurpose frames. 3. Add support for parsing and constructing wake-up frames.
This commit is contained in:
@@ -787,6 +787,218 @@ void TestMacFrameAckGeneration(void)
|
||||
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
|
||||
constexpr uint16_t kMpFcfLongFrame = 1 << 3;
|
||||
constexpr uint16_t kMpFcfDstAddrShift = 4;
|
||||
constexpr uint16_t kMpFcfDstAddrExt = 3 << kMpFcfDstAddrShift;
|
||||
constexpr uint16_t kMpFcfSrcAddrShift = 6;
|
||||
constexpr uint16_t kMpFcfSrcAddrShort = 2 << kMpFcfSrcAddrShift;
|
||||
constexpr uint16_t kMpFcfSrcAddrExt = 3 << kMpFcfSrcAddrShift;
|
||||
constexpr uint16_t kMpFcfPanidPresent = 1 << 8;
|
||||
constexpr uint16_t kMpFcfSecurityEnabled = 1 << 9;
|
||||
constexpr uint16_t kMpFcfSequenceSuppression = 1 << 10;
|
||||
constexpr uint16_t kMpFcfAckRequest = 1 << 14;
|
||||
constexpr uint16_t kMpFcfIePresent = 1 << 15;
|
||||
|
||||
void TestMacWakeupFrameGeneration(void)
|
||||
{
|
||||
constexpr static uint8_t srcExtaddr[] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
|
||||
constexpr static uint8_t dstExtaddr[] = {0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD};
|
||||
constexpr static uint8_t keySource[] = {0, 0, 0, 0x1C};
|
||||
|
||||
constexpr static uint8_t wakeupPsdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0E, 0xCD, 0xAB,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C};
|
||||
|
||||
uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE];
|
||||
Mac::Address src;
|
||||
Mac::Address dst;
|
||||
Mac::Address addr;
|
||||
Mac::TxFrame txFrame;
|
||||
Mac::Frame rxFrame;
|
||||
Mac::ConnectionIe *connectionIe;
|
||||
|
||||
printf("TestMacWakeupFrameGeneration\n");
|
||||
|
||||
src.SetExtended(srcExtaddr);
|
||||
dst.SetExtended(dstExtaddr);
|
||||
txFrame.mPsdu = psdu;
|
||||
txFrame.mLength = 0;
|
||||
txFrame.mRadioType = 0;
|
||||
|
||||
SuccessOrQuit(txFrame.GenerateWakeupFrame(0xface, dst, src));
|
||||
|
||||
// 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.GetPayloadLength() == 0);
|
||||
SuccessOrQuit(txFrame.GetSrcAddr(addr));
|
||||
VerifyOrQuit(CompareAddresses(src, addr));
|
||||
SuccessOrQuit(txFrame.GetDstAddr(addr));
|
||||
VerifyOrQuit(CompareAddresses(dst, addr));
|
||||
|
||||
// Initialize remaining fields and check if the frame has the expected contents
|
||||
txFrame.SetFrameCounter(0xFCFCFCFC);
|
||||
txFrame.SetKeySource(keySource);
|
||||
txFrame.SetKeyId(0x1D);
|
||||
txFrame.GetRendezvousTimeIe()->SetRendezvousTime(0xABCD);
|
||||
connectionIe = txFrame.GetConnectionIe();
|
||||
connectionIe->SetRetryInterval(1);
|
||||
connectionIe->SetRetryCount(12);
|
||||
|
||||
VerifyOrQuit(txFrame.GetRendezvousTimeIe()->GetRendezvousTime() == 0xABCD);
|
||||
VerifyOrQuit(connectionIe->GetRetryInterval() == 1);
|
||||
VerifyOrQuit(connectionIe->GetRetryCount() == 12);
|
||||
VerifyOrQuit(txFrame.GetLength() == sizeof(wakeupPsdu) + txFrame.GetFooterLength());
|
||||
VerifyOrQuit(memcmp(psdu, wakeupPsdu, sizeof(wakeupPsdu)) == 0);
|
||||
|
||||
// Initialize RX Frame with the same PSDU and check if it's recognized as wake-up frame
|
||||
rxFrame.mPsdu = psdu;
|
||||
rxFrame.mLength = txFrame.GetLength();
|
||||
rxFrame.mRadioType = 0;
|
||||
|
||||
SuccessOrQuit(rxFrame.ValidatePsdu());
|
||||
VerifyOrQuit(rxFrame.IsWakeupFrame());
|
||||
}
|
||||
|
||||
void TestMacWakeupFrameDetectionNegative(void)
|
||||
{
|
||||
struct TestCase
|
||||
{
|
||||
uint8_t *mPsdu;
|
||||
uint8_t mLength;
|
||||
};
|
||||
|
||||
uint8_t ackRequestedPsdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfAckRequest | kMpFcfIePresent) >>
|
||||
8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0E, 0xCD, 0xAB,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
|
||||
// Footer
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t shortAddressPsdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrShort,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0E, 0xCD, 0xAB,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
|
||||
// Footer
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t noRendezvousIePsdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
|
||||
// Footer
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t noConnectionIePsdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0E, 0xCD, 0xAB,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x02, 0x1C,
|
||||
// Footer
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t keyIdMode1Psdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x1D,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0E, 0xCD, 0xAB,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
|
||||
// Footer
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const TestCase testCases[] = {
|
||||
{ackRequestedPsdu, sizeof(ackRequestedPsdu)}, {shortAddressPsdu, sizeof(shortAddressPsdu)},
|
||||
{noRendezvousIePsdu, sizeof(noRendezvousIePsdu)}, {noConnectionIePsdu, sizeof(noConnectionIePsdu)},
|
||||
{keyIdMode1Psdu, sizeof(keyIdMode1Psdu)},
|
||||
};
|
||||
|
||||
Mac::Frame rxFrame;
|
||||
|
||||
printf("TestMacWakeupFrameDetectionNegative\n");
|
||||
|
||||
for (const TestCase &testCase : testCases)
|
||||
{
|
||||
rxFrame.mPsdu = testCase.mPsdu;
|
||||
rxFrame.mLength = testCase.mLength;
|
||||
rxFrame.mRadioType = 0;
|
||||
|
||||
SuccessOrQuit(rxFrame.ValidatePsdu());
|
||||
VerifyOrQuit(!rxFrame.IsWakeupFrame());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
@@ -796,6 +1008,10 @@ int main(void)
|
||||
ot::TestMacChannelMask();
|
||||
ot::TestMacFrameApi();
|
||||
ot::TestMacFrameAckGeneration();
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
|
||||
ot::TestMacWakeupFrameGeneration();
|
||||
ot::TestMacWakeupFrameDetectionNegative();
|
||||
#endif
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user