diff --git a/include/openthread-types.h b/include/openthread-types.h index 792ef927a..344c31503 100644 --- a/include/openthread-types.h +++ b/include/openthread-types.h @@ -62,6 +62,18 @@ typedef enum ThreadError kThreadError_NotImplemented = 13, kThreadError_InvalidState = 14, kThreadError_NoTasklets = 15, + + /** + * No acknowledgment was received after macMaxFrameRetries (IEEE 802.15.4-2006). + */ + kThreadError_NoAck = 16, + + /** + * A transmission could not take place due to activity on the channel, i.e., the CSMA-CA mechanism has failed + * (IEEE 802.15.4-2006). + */ + kThreadError_ChannelAccessFailure = 17, + kThreadError_Error = 255, } ThreadError; diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 2a7b6012a..9c6626454 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -55,7 +55,7 @@ static Tasklet sTransmitDoneTask(&Mac::TransmitDoneTask, NULL); void Mac::StartCsmaBackoff(void) { - uint32_t backoffExponent = kMinBE + mCsmaAttempts; + uint32_t backoffExponent = kMinBE + mTransmitAttempts + mCsmaAttempts; uint32_t backoff; if (backoffExponent > kMaxBE) @@ -84,6 +84,7 @@ Mac::Mac(ThreadNetif &aThreadNetif): mRxOnWhenIdle = true; mCsmaAttempts = 0; + mTransmitAttempts = 0; mTransmitBeacon = false; mBeacon.Init(); @@ -499,17 +500,16 @@ void Mac::TransmitDoneTask(void) mAckTimer.Stop(); - if (error != kThreadError_None) + if (error == kThreadError_ChannelAccessFailure && + mCsmaAttempts < kMaxCSMABackoffs) { - if (mCsmaAttempts < kMaxCSMABackoffs) - { - mCsmaAttempts++; - } - + mCsmaAttempts++; StartCsmaBackoff(); ExitNow(); } + mCsmaAttempts = 0; + switch (mState) { case kStateActiveScan: @@ -530,7 +530,7 @@ void Mac::TransmitDoneTask(void) mReceiveTimer.Stop(); } - SentFrame(true); + SentFrame(error == kThreadError_None); break; default: @@ -619,9 +619,9 @@ void Mac::SentFrame(bool aAcked) { otDumpDebgMac("NO ACK", mSendFrame.GetHeader(), 16); - if (mCsmaAttempts < kMaxCSMABackoffs) + if (mTransmitAttempts < kMaxFrameAttempts) { - mCsmaAttempts++; + mTransmitAttempts++; StartCsmaBackoff(); ExitNow(); } @@ -634,7 +634,7 @@ void Mac::SentFrame(bool aAcked) } } - mCsmaAttempts = 0; + mTransmitAttempts = 0; sender = mSendHead; mSendHead = mSendHead->mNext; diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index 015090c33..d3f6dbd35 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -65,19 +65,21 @@ namespace Mac { */ enum { - kMinBE = 3, ///< macMinBE (IEEE 802.15.4-2006) - kMaxBE = 6, ///< macMaxBE (IEEE 802.15.4-2006) - kMaxCSMABackoffs = 12, ///< macMaxCSMABackoffs (IEEE 802.15.4-2006) - kUnitBackoffPeriod = 20, ///< Number of symbols (IEEE 802.15.4-2006) + kMinBE = 3, ///< macMinBE (IEEE 802.15.4-2006) + kMaxBE = 6, ///< macMaxBE (IEEE 802.15.4-2006) + kMaxCSMABackoffs = 4, ///< macMaxCSMABackoffs (IEEE 802.15.4-2006) + kMaxFrameRetries = 15, ///< macMaxFrameRetries (IEEE 802.15.4-2006) + kUnitBackoffPeriod = 20, ///< Number of symbols (IEEE 802.15.4-2006) - kMinBackoff = 16, ///< Minimum backoff (milliseconds). + kMinBackoff = 16, ///< Minimum backoff (milliseconds). + kMaxFrameAttempts = kMaxFrameRetries + 1, ///< Number of transmission attempts. - kAckTimeout = 16, ///< Timeout for waiting on an ACK (milliseconds). - kDataPollTimeout = 100, ///< Timeout for receivint Data Frame (milliseconds). - kNonceSize = 13, ///< Size of IEEE 802.15.4 Nonce (bytes). + kAckTimeout = 16, ///< Timeout for waiting on an ACK (milliseconds). + kDataPollTimeout = 100, ///< Timeout for receivint Data Frame (milliseconds). + kNonceSize = 13, ///< Size of IEEE 802.15.4 Nonce (bytes). - kScanChannelsAll = 0xffff, ///< All channels. - kScanDurationDefault = 200, ///< Default interval between channels (milliseconds). + kScanChannelsAll = 0xffff, ///< All channels. + kScanDurationDefault = 200, ///< Default interval between channels (milliseconds). }; /** @@ -440,6 +442,7 @@ private: uint8_t mDataSequence; bool mRxOnWhenIdle; uint8_t mCsmaAttempts; + uint8_t mTransmitAttempts; bool mTransmitBeacon; bool mActiveScanRequest;