[mac-frame] remove Multipurpose frame format support (#13281)

This commit removes the Multipurpose (MP) frame format support
(`OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME`) and associated
wake-up frame handling.

Multipurpose frame support was originally added as a provisional and
experimental solution for the Wakeup Coordinator / Wake-up End Device
(WED) wake mechanism. However, updated Thread specification designs
decided against using the Multipurpose frame format for wake frames.
Removing this now obsolete MP frame logic cleans up and simplifies
MAC frame parsing and generation ahead of implementing the updated
wake mechanism.

Key changes:
- Removes `OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME` from `mac.h` and
  adds an `#error` check in `openthread-core-config-check.h`.
- Simplifies `Mac::Frame` control field (FCF) parsing and helper methods
  by removing MP-specific frame handling and template helpers.
- Replaces legacy MP wake-up frame helpers in `mac_frame.cpp` with
  temporary placeholder stubs.
- Cleans up unit tests in `test_mac_frame.cpp` related to MP frame
  format.
- Removes the now obsolete `v1_5-cli-p2p-link.exp` test.
This commit is contained in:
Abtin Keshavarzian
2026-07-03 12:53:32 -07:00
committed by GitHub
parent 4c44ff1edb
commit a56a79bcb7
6 changed files with 42 additions and 756 deletions
-286
View File
@@ -782,288 +782,6 @@ 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 kMpFcfDstAddrNone = 0 << kMpFcfDstAddrShift;
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 Mac::WakeupId kWakeupId = 0x1020;
constexpr static uint8_t kSrcExtaddr[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
constexpr static uint8_t kDstExtaddr[] = {0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87};
constexpr static uint8_t kKeySource[] = {0, 0, 0, 0x1c};
constexpr static uint8_t kWakeupPsdu[] = {
// Frame Control
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
// PAN ID
0xce, 0xfa,
// Destination Address
0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0,
// Source Address
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
// 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};
constexpr static uint8_t kWakeupPsdu2[] = {
// Frame Control
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrNone | kMpFcfSrcAddrExt,
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
// PAN ID
0xce, 0xfa,
// No Destination Address
// Source Address
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
// 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
0x07, 0x00, 0x9b, 0xb8, 0xea, 0x01, 0x1c, 0x20, 0x10};
uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE];
Mac::Address src;
Mac::Address dst;
Mac::Address addr;
Mac::WakeupId wakeupId;
Mac::WakeupRequest wakeupRequest;
Mac::TxFrame txFrame;
Mac::Frame rxFrame;
Mac::ConnectionIe *connectionIe;
printf("TestMacWakeupFrameGeneration\n");
src.SetExtended(kSrcExtaddr);
dst.SetExtended(kDstExtaddr);
wakeupRequest.SetExtAddress(dst.GetExtended());
txFrame.mPsdu = psdu;
txFrame.mLength = 0;
txFrame.mRadioType = 0;
SuccessOrQuit(txFrame.GenerateWakeupFrame(0xface, wakeupRequest, src));
// Validate that the frame satisfies the wake-up frame definition
VerifyOrQuit(txFrame.GetType() == Mac::Frame::kTypeMultipurpose);
VerifyOrQuit(!txFrame.GetAckRequest());
VerifyOrQuit(txFrame.Has<Mac::RendezvousTimeIe>());
VerifyOrQuit(txFrame.Has<Mac::ConnectionIe>());
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(kKeySource);
txFrame.SetKeyId(0x1d);
txFrame.Find<Mac::RendezvousTimeIe>()->SetRendezvousTime(0xabcd);
connectionIe = txFrame.Find<Mac::ConnectionIe>();
connectionIe->SetRetryInterval(1);
connectionIe->SetRetryCount(12);
VerifyOrQuit(connectionIe->SetWakeupId(kWakeupId) == kErrorParse);
VerifyOrQuit(txFrame.Find<Mac::RendezvousTimeIe>()->GetRendezvousTime() == 0xabcd);
VerifyOrQuit(connectionIe->GetRetryInterval() == 1);
VerifyOrQuit(connectionIe->GetRetryCount() == 12);
VerifyOrQuit(connectionIe->GetWakeupId(wakeupId) == kErrorParse);
VerifyOrQuit(txFrame.GetLength() == sizeof(kWakeupPsdu) + txFrame.GetFooterLength());
VerifyOrQuit(memcmp(psdu, kWakeupPsdu, sizeof(kWakeupPsdu)) == 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());
// Validate the wake-up frame using the wake-up identifier.
src.SetExtended(kSrcExtaddr);
wakeupRequest.SetWakeupId(kWakeupId);
txFrame.mPsdu = psdu;
txFrame.mLength = 0;
txFrame.mRadioType = 0;
SuccessOrQuit(txFrame.GenerateWakeupFrame(0xface, wakeupRequest, src));
// Validate that the frame satisfies the wake-up frame definition
VerifyOrQuit(txFrame.GetType() == Mac::Frame::kTypeMultipurpose);
VerifyOrQuit(!txFrame.GetAckRequest());
VerifyOrQuit(txFrame.Has<Mac::RendezvousTimeIe>());
VerifyOrQuit(txFrame.Has<Mac::ConnectionIe>());
VerifyOrQuit(txFrame.GetPayloadLength() == 0);
SuccessOrQuit(txFrame.GetSrcAddr(addr));
VerifyOrQuit(CompareAddresses(src, addr));
SuccessOrQuit(txFrame.GetDstAddr(addr));
VerifyOrQuit(addr.IsNone());
// Initialize remaining fields and check if the frame has the expected contents
txFrame.SetFrameCounter(0xfcfcfcfc);
txFrame.SetKeySource(kKeySource);
txFrame.SetKeyId(0x1d);
txFrame.Find<Mac::RendezvousTimeIe>()->SetRendezvousTime(0xabcd);
connectionIe = txFrame.Find<Mac::ConnectionIe>();
connectionIe->SetRetryInterval(1);
connectionIe->SetRetryCount(12);
SuccessOrQuit(connectionIe->SetWakeupId(kWakeupId));
VerifyOrQuit(txFrame.Find<Mac::RendezvousTimeIe>()->GetRendezvousTime() == 0xabcd);
VerifyOrQuit(connectionIe->GetRetryInterval() == 1);
VerifyOrQuit(connectionIe->GetRetryCount() == 12);
SuccessOrQuit(connectionIe->GetWakeupId(wakeupId));
VerifyOrQuit(wakeupId == kWakeupId);
VerifyOrQuit(wakeupRequest.GetWakeupId() == kWakeupId);
VerifyOrQuit(txFrame.GetLength() == sizeof(kWakeupPsdu2) + txFrame.GetFooterLength());
VerifyOrQuit(memcmp(psdu, kWakeupPsdu2, sizeof(kWakeupPsdu2)) == 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)
@@ -1073,10 +791,6 @@ 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;
}