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:
Abtin Keshavarzian
2017-03-08 18:32:48 -08:00
committed by Jonathan Hui
parent 1c18f45bfe
commit 0976e570b8
4 changed files with 53 additions and 3 deletions
+5
View File
@@ -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
View File
@@ -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;
};
+23 -1
View File
@@ -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
+7 -1
View File
@@ -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;