mirror of
https://github.com/espressif/openthread.git
synced 2026-08-19 17:09:51 +00:00
[indirect-sender] add FrameContext class (#4005)
This commit adds a `FrameContext` type (containing all info that need to be saved along with a prepared frame for indirect transmission) and its support in `IndirectSender` and `DataPollHandler`. While the `FrameContext` is defined by the `IndirectSender`, the lower-layer `DataPollHandler` is expected to provide the buffer/object for it to be stored (when the frame is prepared). This model allows different implementations of `DataPollHandler` to adopt different strategies on how to store the context.
This commit is contained in:
committed by
Jonathan Hui
parent
6d07a3eb31
commit
939ac82bf2
@@ -132,7 +132,7 @@ SOURCES_COMMON = \
|
||||
api/sntp_api.cpp \
|
||||
api/tasklet_api.cpp \
|
||||
api/thread_api.cpp \
|
||||
api/thread_ftd_api.cpp \
|
||||
api/thread_ftd_api.cpp \
|
||||
api/udp_api.cpp \
|
||||
coap/coap.cpp \
|
||||
coap/coap_message.cpp \
|
||||
@@ -398,6 +398,7 @@ HEADERS_COMMON = \
|
||||
thread/device_mode.hpp \
|
||||
thread/energy_scan_server.hpp \
|
||||
thread/indirect_sender.hpp \
|
||||
thread/indirect_sender_frame_context.hpp \
|
||||
thread/key_manager.hpp \
|
||||
thread/link_quality.hpp \
|
||||
thread/lowpan.hpp \
|
||||
|
||||
@@ -47,16 +47,19 @@ DataPollHandler::Callbacks::Callbacks(Instance &aInstance)
|
||||
{
|
||||
}
|
||||
|
||||
inline otError DataPollHandler::Callbacks::PrepareFrameForChild(Mac::TxFrame &aFrame, Child &aChild)
|
||||
inline otError DataPollHandler::Callbacks::PrepareFrameForChild(Mac::TxFrame &aFrame,
|
||||
FrameContext &aContext,
|
||||
Child & aChild)
|
||||
{
|
||||
return Get<IndirectSender>().PrepareFrameForChild(aFrame, aChild);
|
||||
return Get<IndirectSender>().PrepareFrameForChild(aFrame, aContext, aChild);
|
||||
}
|
||||
|
||||
inline void DataPollHandler::Callbacks::HandleSentFrameToChild(const Mac::TxFrame &aFrame,
|
||||
const FrameContext &aContext,
|
||||
otError aError,
|
||||
Child & aChild)
|
||||
{
|
||||
Get<IndirectSender>().HandleSentFrameToChild(aFrame, aError, aChild);
|
||||
Get<IndirectSender>().HandleSentFrameToChild(aFrame, aContext, aError, aChild);
|
||||
}
|
||||
|
||||
inline void DataPollHandler::Callbacks::HandleFrameChangeDone(Child &aChild)
|
||||
@@ -69,6 +72,7 @@ inline void DataPollHandler::Callbacks::HandleFrameChangeDone(Child &aChild)
|
||||
DataPollHandler::DataPollHandler(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mIndirectTxChild(NULL)
|
||||
, mFrameContext()
|
||||
, mCallbacks(aInstance)
|
||||
{
|
||||
}
|
||||
@@ -172,7 +176,7 @@ otError DataPollHandler::HandleFrameRequest(Mac::TxFrame &aFrame)
|
||||
|
||||
VerifyOrExit(mIndirectTxChild != NULL, error = OT_ERROR_ABORT);
|
||||
|
||||
SuccessOrExit(error = mCallbacks.PrepareFrameForChild(aFrame, *mIndirectTxChild));
|
||||
SuccessOrExit(error = mCallbacks.PrepareFrameForChild(aFrame, mFrameContext, *mIndirectTxChild));
|
||||
|
||||
if (mIndirectTxChild->GetIndirectTxAttempts() > 0)
|
||||
{
|
||||
@@ -279,7 +283,7 @@ void DataPollHandler::HandleSentFrame(const Mac::TxFrame &aFrame, otError aError
|
||||
break;
|
||||
}
|
||||
|
||||
mCallbacks.HandleSentFrameToChild(aFrame, aError, aChild);
|
||||
mCallbacks.HandleSentFrameToChild(aFrame, mFrameContext, aError, aChild);
|
||||
|
||||
exit:
|
||||
return;
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "common/timer.hpp"
|
||||
#include "mac/mac.hpp"
|
||||
#include "mac/mac_frame.hpp"
|
||||
#include "thread/indirect_sender_frame_context.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
@@ -133,6 +134,17 @@ public:
|
||||
friend class DataPollHandler;
|
||||
|
||||
private:
|
||||
/**
|
||||
* This type defines the frame context associated with a prepared frame.
|
||||
*
|
||||
* Data poll handler treats `FrameContext` as an opaque data type. Data poll handler provides the buffer/object
|
||||
* for the context when a new frame is prepared (from the callback `PrepareFrameForChild()`). It ensures
|
||||
* to save the context along with the prepared frame and provide the same context back in the callback
|
||||
* `HandleSentFrameToChild()` when the indirect transmission of the frame is finished.
|
||||
*
|
||||
*/
|
||||
typedef IndirectSenderBase::FrameContext FrameContext;
|
||||
|
||||
/**
|
||||
* This constructor initializes the data poll handler object.
|
||||
*
|
||||
@@ -144,19 +156,21 @@ public:
|
||||
/**
|
||||
* This callback method requests a frame to be prepared for indirect transmission to a given sleepy child.
|
||||
*
|
||||
* @param[in] aFrame A reference to a MAC frame where the new frame would be placed.
|
||||
* @param[in] aChild The child for which to prepare the frame.
|
||||
* @param[out] aFrame A reference to a MAC frame where the new frame would be placed.
|
||||
* @prarm[out] aContext A reference to a `FrameContext` where the context for the new frame would be placed.
|
||||
* @param[in] aChild The child for which to prepare the frame.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Frame was prepared successfully
|
||||
* @retval OT_ERROR_ABORT Indirect transmission to child should be aborted (no frame for the child).
|
||||
*
|
||||
*/
|
||||
otError PrepareFrameForChild(Mac::TxFrame &aFrame, Child &aChild);
|
||||
otError PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
|
||||
|
||||
/**
|
||||
* This callback method notifies the end of indirect frame transmission to a child.
|
||||
*
|
||||
* @param[in] aFrame The transmitted frame.
|
||||
* @param[in] aContext The context associated with the frame when it was prepared.
|
||||
* @param[in] aError OT_ERROR_NONE when the frame was transmitted successfully,
|
||||
* OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
|
||||
* OT_ERROR_CHANNEL_ACCESS_FAILURE tx failed due to activity on the channel,
|
||||
@@ -164,7 +178,10 @@ public:
|
||||
* @param[in] aChild The child to which the frame was transmitted.
|
||||
*
|
||||
*/
|
||||
void HandleSentFrameToChild(const Mac::TxFrame &aFrame, otError aError, Child &aChild);
|
||||
void HandleSentFrameToChild(const Mac::TxFrame &aFrame,
|
||||
const FrameContext &aContext,
|
||||
otError aError,
|
||||
Child & aChild);
|
||||
|
||||
/**
|
||||
* This callback method notifies that a requested frame change from `RequestFrameChange()` is processed.
|
||||
@@ -249,8 +266,15 @@ private:
|
||||
void HandleSentFrame(const Mac::TxFrame &aFrame, otError aError, Child &aChild);
|
||||
void ProcessPendingPolls(void);
|
||||
|
||||
Child * mIndirectTxChild;
|
||||
Callbacks mCallbacks;
|
||||
// In the current implementation of `DataPollHandler`, we can have a
|
||||
// single indirect tx operation active at MAC layer at each point of
|
||||
// time. `mIndirectTxChild` indicates the child being handled (NULL
|
||||
// indicates no active indirect tx). `mFrameContext` tracks the
|
||||
// context for the prepared frame for the current indirect tx.
|
||||
|
||||
Child * mIndirectTxChild;
|
||||
Callbacks::FrameContext mFrameContext;
|
||||
Callbacks mCallbacks;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,7 +65,6 @@ IndirectSender::IndirectSender(Instance &aInstance)
|
||||
, mEnabled(false)
|
||||
, mSourceMatchController(aInstance)
|
||||
, mDataPollHandler(aInstance)
|
||||
, mMessageNextOffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -320,7 +319,7 @@ void IndirectSender::UpdateIndirectMessage(Child &aChild)
|
||||
}
|
||||
}
|
||||
|
||||
otError IndirectSender::PrepareFrameForChild(Mac::TxFrame &aFrame, Child &aChild)
|
||||
otError IndirectSender::PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message *message = aChild.GetIndirectMessage();
|
||||
@@ -336,12 +335,12 @@ otError IndirectSender::PrepareFrameForChild(Mac::TxFrame &aFrame, Child &aChild
|
||||
switch (message->GetType())
|
||||
{
|
||||
case Message::kTypeIp6:
|
||||
mMessageNextOffset = PrepareDataFrame(aFrame, aChild, *message);
|
||||
aContext.mMessageNextOffset = PrepareDataFrame(aFrame, aChild, *message);
|
||||
break;
|
||||
|
||||
case Message::kTypeSupervision:
|
||||
PrepareEmptyFrame(aFrame, aChild, kSupervisionMsgAckRequest);
|
||||
mMessageNextOffset = message->GetLength();
|
||||
aContext.mMessageNextOffset = message->GetLength();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -432,9 +431,13 @@ void IndirectSender::PrepareEmptyFrame(Mac::TxFrame &aFrame, Child &aChild, bool
|
||||
aFrame.SetFramePending(false);
|
||||
}
|
||||
|
||||
void IndirectSender::HandleSentFrameToChild(const Mac::TxFrame &aFrame, otError aError, Child &aChild)
|
||||
void IndirectSender::HandleSentFrameToChild(const Mac::TxFrame &aFrame,
|
||||
const FrameContext &aContext,
|
||||
otError aError,
|
||||
Child & aChild)
|
||||
{
|
||||
Message *message = aChild.GetIndirectMessage();
|
||||
Message *message = aChild.GetIndirectMessage();
|
||||
uint16_t nextOffset = aContext.mMessageNextOffset;
|
||||
|
||||
VerifyOrExit(mEnabled);
|
||||
|
||||
@@ -451,13 +454,13 @@ void IndirectSender::HandleSentFrameToChild(const Mac::TxFrame &aFrame, otError
|
||||
aChild.SetIndirectTxSuccess(false);
|
||||
|
||||
#if OPENTHREAD_CONFIG_DROP_MESSAGE_ON_FRAGMENT_TX_FAILURE
|
||||
// We set the NextOffset to end of message, since there is no need to
|
||||
// We set the nextOffset to end of message, since there is no need to
|
||||
// send any remaining fragments in the message to the child, if all tx
|
||||
// attempts of current frame already failed.
|
||||
|
||||
if (message != NULL)
|
||||
{
|
||||
mMessageNextOffset = message->GetLength();
|
||||
nextOffset = message->GetLength();
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@@ -467,9 +470,9 @@ void IndirectSender::HandleSentFrameToChild(const Mac::TxFrame &aFrame, otError
|
||||
break;
|
||||
}
|
||||
|
||||
if ((message != NULL) && (mMessageNextOffset < message->GetLength()))
|
||||
if ((message != NULL) && (nextOffset < message->GetLength()))
|
||||
{
|
||||
aChild.SetIndirectFragmentOffset(mMessageNextOffset);
|
||||
aChild.SetIndirectFragmentOffset(nextOffset);
|
||||
mDataPollHandler.HandleNewFrame(aChild);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "mac/data_poll_handler.hpp"
|
||||
#include "mac/mac_frame.hpp"
|
||||
#include "thread/device_mode.hpp"
|
||||
#include "thread/indirect_sender_frame_context.hpp"
|
||||
#include "thread/src_match_controller.hpp"
|
||||
|
||||
namespace ot {
|
||||
@@ -60,7 +61,7 @@ class Child;
|
||||
* This class implements indirect transmission.
|
||||
*
|
||||
*/
|
||||
class IndirectSender : public InstanceLocator
|
||||
class IndirectSender : public InstanceLocator, public IndirectSenderBase
|
||||
{
|
||||
friend class Instance;
|
||||
friend class DataPollHandler::Callbacks;
|
||||
@@ -207,8 +208,11 @@ private:
|
||||
};
|
||||
|
||||
// Callbacks from DataPollHandler
|
||||
otError PrepareFrameForChild(Mac::TxFrame &aFrame, Child &aChild);
|
||||
void HandleSentFrameToChild(const Mac::TxFrame &aFrame, otError aError, Child &aChild);
|
||||
otError PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
|
||||
void HandleSentFrameToChild(const Mac::TxFrame &aFrame,
|
||||
const FrameContext &aContext,
|
||||
otError aError,
|
||||
Child & aChild);
|
||||
void HandleFrameChangeDone(Child &aChild);
|
||||
|
||||
void UpdateIndirectMessage(Child &aChild);
|
||||
@@ -221,7 +225,6 @@ private:
|
||||
bool mEnabled;
|
||||
SourceMatchController mSourceMatchController;
|
||||
DataPollHandler mDataPollHandler;
|
||||
uint16_t mMessageNextOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2019, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions of frame context used for indirect transmission.
|
||||
*/
|
||||
|
||||
#ifndef INDIRECT_SENDER_FRAME_CONTETX_HPP_
|
||||
#define INDIRECT_SENDER_FRAME_CONTETX_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include "utils/wrap_stdint.h"
|
||||
|
||||
namespace ot {
|
||||
|
||||
/**
|
||||
* @addtogroup core-mesh-forwarding
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions frame context used by indirect sender.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class defines the `FrameContext` type.
|
||||
*
|
||||
* This is the base class for `IndirectSender`.
|
||||
*
|
||||
*/
|
||||
class IndirectSenderBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This type defines the frame context used by `IndirectSender`.
|
||||
*
|
||||
* This type specifies all the info that `IndirectSender` requires to be saved along with a prepared frame for
|
||||
* indirect transmission. `IndirectSender` is designed to contain the common code for handling of indirect
|
||||
* transmission to sleepy children and be able to interface to different lower-layer implementation of
|
||||
* `DataPollHandler`. While the `FrameContext` is defined by the `IndirectSender` itself, the lower-layer
|
||||
* (`DataPollHandler`) is expected to provide the buffer/object for context to be stored (it is provided from the
|
||||
* lower-layer callback asking for a frame to be prepared). This model allows different implementations of
|
||||
* `DataPollHandler` to adopt different strategies on how to save the context.
|
||||
*
|
||||
*/
|
||||
struct FrameContext
|
||||
{
|
||||
friend class IndirectSender;
|
||||
|
||||
private:
|
||||
uint16_t mMessageNextOffset; ///< The next offset into the message associated with the prepared frame.
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // INDIRECT_SENDER_FRAME_CONTETX_HPP_
|
||||
Reference in New Issue
Block a user