mirror of
https://github.com/espressif/openthread.git
synced 2026-08-25 19:59:51 +00:00
[mac] redesign Information Element (IE) processing and generation (#13263)
This commit redesigns IEEE 802.15.4 Information Element (IE) handling by introducing dedicated subclass definitions (`CslIe`, `TimeIe`, `ConnectionIe`, `RendezvousTimeIe`, `LinkMetricsProbingIe`, etc.) inheriting from `HeaderIe` or `VendorIe`. In addition, `Mac::Frame` is updated with generic template methods: - `Has<IeType>()`: Checks if the frame contains a well-formed instance of the specified IE subclass. - `Find<IeType>()`: Finds, validates and returns a type-safe pointer to the IE. Key benefits of this redesign: - Streamlined IE Generation: Constructing and populating IEs is significantly simplified. Each subclass exposes a unified `Init()` method that cleanly computes the exact IE content length, sets the Element ID and known content (e.g. vendor OUI) in a single step. - True Encapsulation: Each IE subclass serves as the single source of truth for its Element ID (`kId`), content layout, and structural validation logic (`IsValid()`). Callers no longer pass magic ID constants or perform error-prone pointer arithmetic. - By implementing `HeaderIe::ValidateAs<IeType>()` as a static polymorphic matcher passed to `FindHeaderIe()`, the compiler devirtualizes and inlines ID match and content verifications directly into MAC frame parsing loops. - Scalable Integration: Adding new Information Elements is trivial. Defining a new subclass automatically equips MAC frame handling with type-safe search without bloating `Mac::Frame` with ad-hoc getter methods.
This commit is contained in:
@@ -761,7 +761,7 @@ void TestMacFrameAckGeneration(void)
|
||||
|
||||
SuccessOrQuit(ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data)));
|
||||
|
||||
csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
|
||||
csl = ackFrame.Find<Mac::CslIe>();
|
||||
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<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
|
||||
ackFrame.UpdateCslIe(123, 456);
|
||||
csl = ackFrame.Find<Mac::CslIe>();
|
||||
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<Mac::RendezvousTimeIe>());
|
||||
VerifyOrQuit(txFrame.Has<Mac::ConnectionIe>());
|
||||
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<Mac::RendezvousTimeIe>()->SetRendezvousTime(0xabcd);
|
||||
connectionIe = txFrame.Find<Mac::ConnectionIe>();
|
||||
connectionIe->SetRetryInterval(1);
|
||||
connectionIe->SetRetryCount(12);
|
||||
VerifyOrQuit(connectionIe->SetWakeupId(kWakeupId) == kErrorParse);
|
||||
|
||||
VerifyOrQuit(txFrame.GetRendezvousTimeIe()->GetRendezvousTime() == 0xabcd);
|
||||
VerifyOrQuit(txFrame.Find<Mac::RendezvousTimeIe>()->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<Mac::RendezvousTimeIe>());
|
||||
VerifyOrQuit(txFrame.Has<Mac::ConnectionIe>());
|
||||
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<Mac::RendezvousTimeIe>()->SetRendezvousTime(0xabcd);
|
||||
connectionIe = txFrame.Find<Mac::ConnectionIe>();
|
||||
connectionIe->SetRetryInterval(1);
|
||||
connectionIe->SetRetryCount(12);
|
||||
SuccessOrQuit(connectionIe->SetWakeupId(kWakeupId));
|
||||
|
||||
VerifyOrQuit(txFrame.GetRendezvousTimeIe()->GetRendezvousTime() == 0xabcd);
|
||||
VerifyOrQuit(txFrame.Find<Mac::RendezvousTimeIe>()->GetRendezvousTime() == 0xabcd);
|
||||
VerifyOrQuit(connectionIe->GetRetryInterval() == 1);
|
||||
VerifyOrQuit(connectionIe->GetRetryCount() == 12);
|
||||
SuccessOrQuit(connectionIe->GetWakeupId(wakeupId));
|
||||
|
||||
Reference in New Issue
Block a user