From 9339230acd575ec10ae5a49db16a77c286f41f56 Mon Sep 17 00:00:00 2001 From: pvanhorn Date: Thu, 18 Jan 2018 14:48:30 -0800 Subject: [PATCH] [mac] add feature to transmit out of band 15.4 frames (#2488) --- include/openthread/link.h | 12 +++++++ src/core/api/link_api.cpp | 7 ++++ src/core/mac/mac.cpp | 74 ++++++++++++++++++++++++++++++++++++--- src/core/mac/mac.hpp | 16 +++++++++ 4 files changed, 104 insertions(+), 5 deletions(-) diff --git a/include/openthread/link.h b/include/openthread/link.h index c226435be..16f343ac8 100644 --- a/include/openthread/link.h +++ b/include/openthread/link.h @@ -150,6 +150,18 @@ OTAPI otError OTCALL otLinkSendDataRequest(otInstance *aInstance); */ OTAPI bool OTCALL otLinkIsInTransmitState(otInstance *aInstance); +/** + * This function enqueues an IEEE 802.15.4 out of band Frame for transmission. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @parma[in] aOobFrame A pointer to the frame to transmit. + * + * @retval OT_ERROR_NONE Successfully enqueued an IEEE 802.15.4 Data Request message. + * @retval OT_ERROR_ALREADY An IEEE 802.15.4 out of band frame is already enqueued. + * + */ +OTAPI otError OTCALL otLinkOutOfBandTransmitRequest(otInstance *aInstance, otRadioFrame *aOobFrame); + /** * Get the IEEE 802.15.4 channel. * diff --git a/src/core/api/link_api.cpp b/src/core/api/link_api.cpp index 48470f324..0538bd7f8 100644 --- a/src/core/api/link_api.cpp +++ b/src/core/api/link_api.cpp @@ -358,3 +358,10 @@ bool otLinkIsInTransmitState(otInstance *aInstance) return instance.GetThreadNetif().GetMac().IsInTransmitState(); } + +otError otLinkOutOfBandTransmitRequest(otInstance *aInstance, otRadioFrame *aOobFrame) +{ + Instance &instance = *static_cast(aInstance); + + return instance.GetThreadNetif().GetMac().SendOutOfBandFrameRequest(aOobFrame); +} diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index b19dfebba..7c0be95e8 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -83,6 +83,7 @@ Mac::Mac(Instance &aInstance): mPendingEnergyScan(false), mPendingTransmitBeacon(false), mPendingTransmitData(false), + mPendingTransmitOobFrame(false), mPendingWaitingForData(false), mRxOnWhenIdle(false), mBeaconsEnabled(false), @@ -116,6 +117,7 @@ Mac::Mac(Instance &aInstance): mFilter(), #endif // OPENTHREAD_ENABLE_MAC_FILTER mTxFrame(static_cast(otPlatRadioGetTransmitBuffer(&aInstance))), + mOobFrame(NULL), mKeyIdMode2FrameCounter(0) { GenerateExtAddress(&mExtAddress); @@ -184,7 +186,8 @@ bool Mac::IsEnergyScanInProgress(void) bool Mac::IsInTransmitState(void) { - return (mOperation == kOperationTransmitData) || (mOperation == kOperationTransmitBeacon); + return (mOperation == kOperationTransmitData) || + (mOperation == kOperationTransmitBeacon) || (mOperation == kOperationTransmitOutOfBandFrame); } otError Mac::ConvertBeaconToActiveScanResult(Frame *aBeaconFrame, otActiveScanResult &aResult) @@ -499,6 +502,20 @@ exit: return error; } +otError Mac::SendOutOfBandFrameRequest(otRadioFrame *aOobFrame) +{ + otError error = OT_ERROR_NONE; + + VerifyOrExit(mOobFrame == NULL, error = OT_ERROR_ALREADY); + + mOobFrame = static_cast(aOobFrame); + + StartOperation(kOperationTransmitOutOfBandFrame); + +exit: + return error; +} + void Mac::UpdateIdleMode(void) { VerifyOrExit(mOperation == kOperationIdle); @@ -554,6 +571,10 @@ void Mac::StartOperation(Operation aOperation) case kOperationWaitingForData: mPendingWaitingForData = true; break; + + case kOperationTransmitOutOfBandFrame: + mPendingTransmitOobFrame = true; + break; } if (mOperation == kOperationIdle) @@ -592,6 +613,12 @@ void Mac::PerformOperation(void) mOperation = kOperationWaitingForData; RadioReceive(mChannel); } + else if (mPendingTransmitOobFrame) + { + mPendingTransmitOobFrame = false; + mOperation = kOperationTransmitOutOfBandFrame; + StartCsmaBackoff(); + } else if (mPendingActiveScan) { mPendingActiveScan = false; @@ -884,10 +911,31 @@ void Mac::HandleBeginTransmit(Timer &aTimer) aTimer.GetOwner().HandleBeginTransmit(); } +Frame *Mac::GetOperationFrame(void) +{ + Frame *frame = NULL; + + switch (mOperation) + { + case kOperationTransmitOutOfBandFrame: + frame = mOobFrame; + break; + + default: + frame = mTxFrame; + break; + } + + assert(frame != NULL); + + return frame; +} + void Mac::HandleBeginTransmit(void) { - Frame &sendFrame(*mTxFrame); otError error = OT_ERROR_NONE; + bool applyTransmitSecurity = true; + Frame &sendFrame(*GetOperationFrame()); #if OPENTHREAD_CONFIG_DISABLE_CCA_ON_LAST_ATTEMPT @@ -933,13 +981,20 @@ void Mac::HandleBeginTransmit(void) break; + case kOperationTransmitOutOfBandFrame: + applyTransmitSecurity = false; + break; + default: assert(false); break; } - // Security Processing - ProcessTransmitSecurity(sendFrame); + if (applyTransmitSecurity) + { + // Security Processing + ProcessTransmitSecurity(sendFrame); + } } error = RadioReceive(sendFrame.GetChannel()); @@ -958,7 +1013,7 @@ exit: if (error != OT_ERROR_NONE) { - HandleTransmitDone(mTxFrame, NULL, OT_ERROR_ABORT); + HandleTransmitDone(&sendFrame, NULL, OT_ERROR_ABORT); } } @@ -1177,6 +1232,11 @@ void Mac::HandleTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otEr break; } + case kOperationTransmitOutOfBandFrame: + mOobFrame = NULL; + FinishOperation(); + break; + default: assert(false); break; @@ -1942,6 +2002,10 @@ const char *Mac::OperationToString(Operation aOperation) case kOperationWaitingForData: retval = "WaitingForData"; break; + + case kOperationTransmitOutOfBandFrame: + retval = "TransmitOobFrame"; + break; } return retval; diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index c90b75c87..6bea3afd3 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -347,6 +347,18 @@ public: */ otError SendFrameRequest(Sender &aSender); + /** + * This method registers a Out of Band frame for MAC Transmission. + * An Out of Band frame is one that was generated outside of OpenThread. + * + * @param[in] aOobFrame A pointer to the frame. + * + * @retval OT_ERROR_NONE Successfully registered the frame. + * @retval OT_ERROR_ALREADY MAC layer is busy sending a previously registered frame. + * + */ + otError SendOutOfBandFrameRequest(otRadioFrame *aOobFrame); + /** * This method generates a random IEEE 802.15.4 Extended Address. * @@ -625,6 +637,7 @@ private: kOperationTransmitBeacon, kOperationTransmitData, kOperationWaitingForData, + kOperationTransmitOutOfBandFrame, }; void GenerateNonce(const ExtAddress &aAddress, uint32_t aFrameCounter, uint8_t aSecurityLevel, uint8_t *aNonce); @@ -637,6 +650,7 @@ private: void SendBeacon(Frame &aFrame); void StartBackoff(void); otError HandleMacCommand(Frame &aFrame); + Frame *GetOperationFrame(void); static void HandleMacTimer(Timer &aTimer); void HandleMacTimer(void); @@ -668,6 +682,7 @@ private: bool mPendingEnergyScan : 1; bool mPendingTransmitBeacon : 1; bool mPendingTransmitData : 1; + bool mPendingTransmitOobFrame : 1; bool mPendingWaitingForData : 1; bool mRxOnWhenIdle : 1; bool mBeaconsEnabled : 1; @@ -720,6 +735,7 @@ private: #endif // OPENTHREAD_ENABLE_MAC_FILTER Frame *mTxFrame; + Frame *mOobFrame; otMacCounters mCounters; uint32_t mKeyIdMode2FrameCounter;