mirror of
https://github.com/espressif/openthread.git
synced 2026-09-15 05:30:09 +00:00
Send quick data poll if "pending frame" bit was set in ack but no data frame received. (#1437)
This commit makes the following changes: - A new callback `DataPollTimeoutHandler` is added to `Mac::Receiver` class which is used to indicate when a data request command (data poll) timeout occurs, i.e., when the ack in response to a data request command indicated a frame is pending but no frame was received after the timeout interval. - Adds new logic in `MeshForwarder` to send quick data polls (up to a fixed number of attempts) if a data poll timeout happens.
This commit is contained in:
committed by
Jonathan Hui
parent
1c18f45bfe
commit
0976e570b8
@@ -996,6 +996,11 @@ void Mac::HandleReceiveTimer(void)
|
||||
{
|
||||
otLogDebgMac(GetInstance(), "data poll timeout!");
|
||||
|
||||
for (Receiver *receiver = mReceiveHead; receiver; receiver = receiver->mNext)
|
||||
{
|
||||
receiver->HandleDataPollTimeout();
|
||||
}
|
||||
|
||||
if (mState == kStateIdle)
|
||||
{
|
||||
NextOperation();
|
||||
|
||||
+18
-1
@@ -102,23 +102,40 @@ public:
|
||||
*/
|
||||
typedef void (*ReceiveFrameHandler)(void *aContext, Frame &aFrame);
|
||||
|
||||
/**
|
||||
* This function pointer is called on a data request command (data poll) timeout, i.e., when the ack in response to
|
||||
* a data request command indicated a frame is pending, but no frame was received after `kDataPollTimeout` interval.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
typedef void (*DataPollTimeoutHandler)(void *aContext);
|
||||
|
||||
/**
|
||||
* This constructor creates a MAC receiver client.
|
||||
*
|
||||
* @param[in] aReceiveFrameHandler A pointer to a function that is called on MAC frame reception.
|
||||
* @param[in] aPollTimeoutHandler A pointer to a function called on data poll timeout (may be set to NULL).
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
Receiver(ReceiveFrameHandler aReceiveFrameHandler, void *aContext) {
|
||||
Receiver(ReceiveFrameHandler aReceiveFrameHandler, DataPollTimeoutHandler aPollTimeoutHandler, void *aContext) {
|
||||
mReceiveFrameHandler = aReceiveFrameHandler;
|
||||
mPollTimeoutHandler = aPollTimeoutHandler;
|
||||
mContext = aContext;
|
||||
mNext = NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
void HandleReceivedFrame(Frame &frame) { mReceiveFrameHandler(mContext, frame); }
|
||||
void HandleDataPollTimeout(void) {
|
||||
if (mPollTimeoutHandler != NULL) {
|
||||
mPollTimeoutHandler(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
ReceiveFrameHandler mReceiveFrameHandler;
|
||||
DataPollTimeoutHandler mPollTimeoutHandler;
|
||||
void *mContext;
|
||||
Receiver *mNext;
|
||||
};
|
||||
|
||||
@@ -55,7 +55,7 @@ using Thread::Encoding::BigEndian::HostSwap16;
|
||||
namespace Thread {
|
||||
|
||||
MeshForwarder::MeshForwarder(ThreadNetif &aThreadNetif):
|
||||
mMacReceiver(&MeshForwarder::HandleReceivedFrame, this),
|
||||
mMacReceiver(&MeshForwarder::HandleReceivedFrame, &MeshForwarder::HandleDataPollTimeout, this),
|
||||
mMacSender(&MeshForwarder::HandleFrameRequest, &MeshForwarder::HandleSentFrame, this),
|
||||
mDiscoverTimer(aThreadNetif.GetIp6().mTimerScheduler, &MeshForwarder::HandleDiscoverTimer, this),
|
||||
mPollTimer(aThreadNetif.GetIp6().mTimerScheduler, &MeshForwarder::HandlePollTimer, this),
|
||||
@@ -76,6 +76,7 @@ MeshForwarder::MeshForwarder(ThreadNetif &aThreadNetif):
|
||||
mRestoreChannel(0),
|
||||
mRestorePanId(Mac::kPanIdBroadcast),
|
||||
mScanning(false),
|
||||
mBacktoBackPollTimeoutCounter(0),
|
||||
mNetif(aThreadNetif),
|
||||
mSrcMatchEnabled(false)
|
||||
{
|
||||
@@ -1821,6 +1822,8 @@ void MeshForwarder::HandleReceivedFrame(Mac::Frame &aFrame)
|
||||
ExitNow(error = kThreadError_InvalidState);
|
||||
}
|
||||
|
||||
mBacktoBackPollTimeoutCounter = 0;
|
||||
|
||||
SuccessOrExit(error = aFrame.GetSrcAddr(macSource));
|
||||
SuccessOrExit(aFrame.GetDstAddr(macDest));
|
||||
|
||||
@@ -2193,4 +2196,23 @@ exit:
|
||||
{}
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleDataPollTimeout(void *aContext)
|
||||
{
|
||||
static_cast<MeshForwarder *>(aContext)->HandleDataPollTimeout();
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleDataPollTimeout(void)
|
||||
{
|
||||
mBacktoBackPollTimeoutCounter++;
|
||||
|
||||
if (mBacktoBackPollTimeoutCounter <= kQuickPollsAfterTimout)
|
||||
{
|
||||
SendMacDataRequest();
|
||||
}
|
||||
else
|
||||
{
|
||||
mBacktoBackPollTimeoutCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
@@ -254,6 +254,7 @@ private:
|
||||
{
|
||||
kStateUpdatePeriod = 1000, ///< State update period in milliseconds.
|
||||
kDataRequestRetryDelay = 200, ///< Retry delay in milliseconds (for sending data request if no buffer).
|
||||
kQuickPollsAfterTimout = 5, ///< Maximum number of quick data poll tx in case of back-to-back poll timeouts.
|
||||
};
|
||||
|
||||
enum
|
||||
@@ -310,6 +311,9 @@ private:
|
||||
static void HandleReceivedFrame(void *aContext, Mac::Frame &aFrame);
|
||||
void HandleReceivedFrame(Mac::Frame &aFrame);
|
||||
|
||||
static void HandleDataPollTimeout(void *aContext);
|
||||
void HandleDataPollTimeout(void);
|
||||
|
||||
static ThreadError HandleFrameRequest(void *aContext, Mac::Frame &aFrame);
|
||||
ThreadError HandleFrameRequest(Mac::Frame &aFrame);
|
||||
|
||||
@@ -342,7 +346,7 @@ private:
|
||||
uint16_t mFragTag;
|
||||
uint16_t mMessageNextOffset;
|
||||
uint32_t mPollPeriod;
|
||||
uint32_t mAssignPollPeriod; ///< only for certification test
|
||||
uint32_t mAssignPollPeriod;
|
||||
|
||||
uint32_t mSendMessageFrameCounter;
|
||||
Message *mSendMessage;
|
||||
@@ -369,6 +373,8 @@ private:
|
||||
uint16_t mRestorePanId;
|
||||
bool mScanning;
|
||||
|
||||
uint8_t mBacktoBackPollTimeoutCounter;
|
||||
|
||||
ThreadNetif &mNetif;
|
||||
|
||||
bool mSrcMatchEnabled;
|
||||
|
||||
Reference in New Issue
Block a user