mirror of
https://github.com/espressif/openthread.git
synced 2026-08-09 12:17:47 +00:00
[link-quality] track MAC frame and message error rates (#2520)
This commit implement a new feature to allow the tracking of tx error rates at two layers: - At PHY/MAC layer for MAC frame transmissions (frame tx error rate): Error rate is maintained per link/neighbor. A frame transmission attempt is considered failed if the frame is sent over the channel, but no acknowledgment frame is received from the neighbor. - Above MAC layer for message transmissions (message error rate): A larger (IPv6) message may be fragmented and sent as multiple MAC frames. The message transmission is considered failed, if any of its fragments fail after all retry attempts. Message error rate is maintained per link/neighbor and includes both direct and indirect message transmissions. Configuration option `OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING` can be used to enable/disable this feature. By default it is enabled. `otChildInfo` and `otNeighborInfo` structs are updated to provide the error rates for a child or neighbor.
This commit is contained in:
committed by
Jonathan Hui
parent
9190aa21c4
commit
68a605f22e
@@ -895,6 +895,8 @@ typedef enum
|
||||
/**
|
||||
* This structure holds diagnostic information for a neighboring Thread node
|
||||
*
|
||||
* `mFrameErrorRate` and `mMessageErrorRate` require `OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING` feature to be
|
||||
* enabled.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@@ -906,6 +908,8 @@ typedef struct
|
||||
uint8_t mLinkQualityIn; ///< Link Quality In
|
||||
int8_t mAverageRssi; ///< Average RSSI
|
||||
int8_t mLastRssi; ///< Last observed RSSI
|
||||
uint16_t mFrameErrorRate; ///< Frame error rate (0xffff->100%). Requires error tracking feature.
|
||||
uint16_t mMessageErrorRate; ///< (IPv6) msg error rate (0xffff->100%). Requires error tracking feature.
|
||||
bool mRxOnWhenIdle : 1; ///< rx-on-when-idle
|
||||
bool mSecureDataRequest : 1; ///< Secure Data Requests
|
||||
bool mFullFunction : 1; ///< Full Function Device
|
||||
@@ -920,6 +924,9 @@ typedef int16_t otNeighborInfoIterator; ///< Used to iterate through neighbor
|
||||
/**
|
||||
* This structure holds diagnostic information for a Thread Child
|
||||
*
|
||||
* `mFrameErrorRate` and `mMessageErrorRate` require `OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING` feature to be
|
||||
* enabled.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@@ -932,6 +939,8 @@ typedef struct
|
||||
uint8_t mLinkQualityIn; ///< Link Quality In
|
||||
int8_t mAverageRssi; ///< Average RSSI
|
||||
int8_t mLastRssi; ///< Last observed RSSI
|
||||
uint16_t mFrameErrorRate; ///< Frame error rate (0xffff->100%). Requires error tracking feature.
|
||||
uint16_t mMessageErrorRate; ///< (IPv6) msg error rate (0xffff->100%). Requires error tracking feature.
|
||||
bool mRxOnWhenIdle : 1; ///< rx-on-when-idle
|
||||
bool mSecureDataRequest : 1; ///< Secure Data Requests
|
||||
bool mFullFunction : 1; ///< Full Function Device
|
||||
|
||||
@@ -113,6 +113,7 @@ struct MessageInfo
|
||||
bool mLinkSecurity : 1; ///< Indicates whether or not link security is enabled.
|
||||
uint8_t mPriority : 2; ///< Identifies the message priority level (lower value is higher priority).
|
||||
bool mInPriorityQ : 1; ///< Indicates whether the message is queued in normal or priority queue.
|
||||
bool mTxSuccess : 1; ///< Indicates whether the direct tx of the message was successful.
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -602,6 +603,24 @@ public:
|
||||
*/
|
||||
void SetDirectTransmission(void) { mBuffer.mHead.mInfo.mDirectTx = true; }
|
||||
|
||||
/**
|
||||
* This methods indicates whether the direct transmission of message was successful.
|
||||
*
|
||||
* @retval TRUE If direct transmission of message was successful (all fragments were delivered and acked).
|
||||
* @retval FALSE If direct transmission of message failed (at least one fragment failed).
|
||||
*
|
||||
*/
|
||||
bool GetTxSuccess(void) const { return mBuffer.mHead.mInfo.mTxSuccess; }
|
||||
|
||||
/**
|
||||
* This methods sets whether the direct transmission of message was successful.
|
||||
*
|
||||
* @param[in] aTxSuccess TRUE if the direct transmission is successful, FALSE otherwise (i.e., at least one
|
||||
* fragment transmission failed).
|
||||
*
|
||||
*/
|
||||
void SetTxSuccess(bool aTxSuccess) { mBuffer.mHead.mInfo.mTxSuccess = aTxSuccess; }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not link security is enabled for the message.
|
||||
*
|
||||
|
||||
+38
-5
@@ -1077,6 +1077,8 @@ void Mac::HandleTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otEr
|
||||
bool framePending = false;
|
||||
bool ccaSuccess = true;
|
||||
Address dstAddr;
|
||||
bool ackRequested;
|
||||
Neighbor *neighbor;
|
||||
|
||||
// Stop the ack timer.
|
||||
|
||||
@@ -1127,6 +1129,40 @@ void Mac::HandleTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otEr
|
||||
|
||||
mCsmaAttempts = 0;
|
||||
|
||||
sendFrame.GetDstAddr(dstAddr);
|
||||
neighbor = GetNetif().GetMle().GetNeighbor(dstAddr);
|
||||
ackRequested = sendFrame.GetAckRequest();
|
||||
|
||||
#if OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
|
||||
|
||||
// Record frame transmission success/failure state (for a neighbor).
|
||||
|
||||
if ((neighbor != NULL) && ackRequested)
|
||||
{
|
||||
bool frameTxSuccess = true;
|
||||
|
||||
// CCA or abort errors are excluded from frame tx error
|
||||
// rate tracking, since when they occur, the frame is
|
||||
// not actually sent over the air.
|
||||
|
||||
switch (aError)
|
||||
{
|
||||
case OT_ERROR_NO_ACK:
|
||||
frameTxSuccess = false;
|
||||
|
||||
// Fall through
|
||||
|
||||
case OT_ERROR_NONE:
|
||||
neighbor->GetLinkInfo().AddFrameTxStatus(frameTxSuccess);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
|
||||
|
||||
// Determine whether to re-transmit the frame.
|
||||
|
||||
mTransmitAttempts++;
|
||||
@@ -1154,12 +1190,9 @@ void Mac::HandleTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otEr
|
||||
|
||||
// Process the ack frame for "frame pending".
|
||||
|
||||
sendFrame.GetDstAddr(dstAddr);
|
||||
|
||||
if (aError == OT_ERROR_NONE && sendFrame.GetAckRequest() && aAckFrame != NULL)
|
||||
if (aError == OT_ERROR_NONE && ackRequested && aAckFrame != NULL)
|
||||
{
|
||||
Frame &ackFrame = *static_cast<Frame *>(aAckFrame);
|
||||
Neighbor *neighbor = GetNetif().GetMle().GetNeighbor(dstAddr);
|
||||
|
||||
framePending = ackFrame.GetFramePending();
|
||||
|
||||
@@ -1187,7 +1220,7 @@ void Mac::HandleTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otEr
|
||||
mCounters.mTxUnicast++;
|
||||
}
|
||||
|
||||
if (sendFrame.GetAckRequest())
|
||||
if (ackRequested)
|
||||
{
|
||||
mCounters.mTxAckRequested++;
|
||||
|
||||
|
||||
@@ -946,6 +946,49 @@
|
||||
#define OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW 512
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
|
||||
*
|
||||
* Define as 1 to enable transmission error rate tracking (for both MAC frames and IPv6 messages)
|
||||
*
|
||||
* When enabled, OpenThread will track average error rate of MAC frame transmissions and IPv6 message error rate for
|
||||
* every neighbor.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
|
||||
#define OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_FRAME_TX_ERR_RATE_AVERAGING_WINDOW
|
||||
*
|
||||
* Applicable only if error rate tracking is enabled (i.e., `OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING` is set).
|
||||
*
|
||||
* OpenThread's MAC implementation maintains the average error rate of MAC frame transmissions per neighbor. This
|
||||
* parameter specifies the window (in terms of number of frames/sample) over which the average error rate is maintained.
|
||||
* Practically, the average value can be considered as the percentage of failed (no ack) MAC frame transmissions over
|
||||
* (approximately) last AVERAGING_WINDOW frame transmission attempts to a specific neighbor.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_FRAME_TX_ERR_RATE_AVERAGING_WINDOW
|
||||
#define OPENTHREAD_CONFIG_FRAME_TX_ERR_RATE_AVERAGING_WINDOW 128
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_IPV6_TX_ERR_RATE_AVERAGING_WINDOW
|
||||
*
|
||||
* Applicable only if error rate tracking is enabled (i.e., `OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING` is set).
|
||||
*
|
||||
* OpenThread maintains the average error rate of IPv6 messages per neighbor. This parameter specifies the
|
||||
* window (in terms of number of messages) over which the average error rate is maintained. Practically, the average
|
||||
* value can be considered as the percentage of failed (no ack) messages over (approximately) last AVERAGING_WINDOW
|
||||
* IPv6 messages sent to a specific neighbor.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_IPV6_TX_ERR_RATE_AVERAGING_WINDOW
|
||||
#define OPENTHREAD_CONFIG_IPV6_TX_ERR_RATE_AVERAGING_WINDOW 128
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_CHANNEL_MONITOR_SAMPLE_INTERVAL
|
||||
*
|
||||
|
||||
@@ -50,14 +50,14 @@ static const char *const kDigitsString[8] =
|
||||
|
||||
void SuccessRateTracker::AddSample(bool aSuccess, uint16_t aWeight)
|
||||
{
|
||||
uint32_t oldAverage = mSuccessRate;
|
||||
uint32_t newValue = (aSuccess) ? kMaxRateValue : 0;
|
||||
uint32_t oldAverage = mFailureRate;
|
||||
uint32_t newValue = (aSuccess) ? 0 : kMaxRateValue;
|
||||
uint32_t n = aWeight;
|
||||
|
||||
// `n/2` is added to the sum to ensure rounding the value to the nearest integer when dividing by `n`
|
||||
// (e.g., 1.2 -> 1, 3.5 -> 4).
|
||||
|
||||
mSuccessRate = static_cast<uint16_t>(((oldAverage * (n - 1)) + newValue + (n / 2)) / n);
|
||||
mFailureRate = static_cast<uint16_t>(((oldAverage * (n - 1)) + newValue + (n / 2)) / n);
|
||||
}
|
||||
|
||||
void RssAverager::Reset(void)
|
||||
|
||||
@@ -71,13 +71,13 @@ public:
|
||||
* After initialization the tracker starts with success rate 100% (failure rate 0%).
|
||||
*
|
||||
*/
|
||||
SuccessRateTracker(void): mSuccessRate(kMaxRateValue) { }
|
||||
SuccessRateTracker(void): mFailureRate(0) { }
|
||||
|
||||
/**
|
||||
* This method resets the tracker to its initialized state, setting success rate to 100%.
|
||||
*
|
||||
*/
|
||||
void Reset(void) { mSuccessRate = kMaxRateValue; }
|
||||
void Reset(void) { mFailureRate = 0; }
|
||||
|
||||
/**
|
||||
* This method adds a sample (success or failure) to `SuccessRateTracker`.
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
* @retval the average failure rate `[0-kMaxRateValue]` with `kMaxRateValue` corresponding to 100%.
|
||||
*
|
||||
*/
|
||||
uint16_t GetFailureRate(void) const { return kMaxRateValue - mSuccessRate; }
|
||||
uint16_t GetFailureRate(void) const { return mFailureRate; }
|
||||
|
||||
/**
|
||||
* This method returns the average success rate.
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
* @retval the average success rate as [0-kMaxRateValue] with `kMaxRateValue` corresponding to 100%.
|
||||
*
|
||||
*/
|
||||
uint16_t GetSuccessRate(void) const { return mSuccessRate; }
|
||||
uint16_t GetSuccessRate(void) const { return kMaxRateValue - mFailureRate; }
|
||||
|
||||
private:
|
||||
enum
|
||||
@@ -110,7 +110,7 @@ private:
|
||||
kDefaultWeight = 64,
|
||||
};
|
||||
|
||||
uint16_t mSuccessRate;
|
||||
uint16_t mFailureRate;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -121,8 +121,6 @@ private:
|
||||
*/
|
||||
class RssAverager
|
||||
{
|
||||
friend class LinkQualityInfo;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
@@ -212,9 +210,8 @@ private:
|
||||
|
||||
// Member variables fit into two bytes.
|
||||
|
||||
uint16_t mAverage : 11; // The raw average signal strength value (stored as RSS times precision multiple).
|
||||
uint8_t mCount : 3; // Number of RSS values added to averager so far (limited to 2^kCoeffBitShift-1).
|
||||
uint8_t mLinkQuality : 2; // Used by friend class LinkQualityInfo to store LinkQuality (0-3) value.
|
||||
uint16_t mAverage : 11; // The raw average signal strength value (stored as RSS times precision multiple).
|
||||
uint16_t mCount : 5; // Number of RSS values added to averager so far (limited to 2^kCoeffBitShift-1).
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -307,7 +304,7 @@ public:
|
||||
* @returns The current link quality value (value 0-3 as per Thread specification).
|
||||
*
|
||||
*/
|
||||
uint8_t GetLinkQuality(void) const { return mRssAverager.mLinkQuality; }
|
||||
uint8_t GetLinkQuality(void) const { return mLinkQuality; }
|
||||
|
||||
/**
|
||||
* Returns the most recent RSS value.
|
||||
@@ -317,6 +314,58 @@ public:
|
||||
*/
|
||||
int8_t GetLastRss(void) const { return mLastRss; }
|
||||
|
||||
#if OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
|
||||
|
||||
/**
|
||||
* This method adds a MAC frame transmission status (success/failure) and updates the frame tx error rate.
|
||||
*
|
||||
* @param[in] aTxStatus Success/Failure of MAC frame transmission (`true` -> success, `false` -> failure).
|
||||
*
|
||||
*/
|
||||
void AddFrameTxStatus(bool aTxStatus) {
|
||||
mFrameErrorRate.AddSample(aTxStatus, OPENTHREAD_CONFIG_FRAME_TX_ERR_RATE_AVERAGING_WINDOW);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds a message transmission status (success/failure) and updates the message error rate.
|
||||
*
|
||||
* @param[in] aTxStatus Success/Failure of message (`true` -> success, `false` -> message tx failed).
|
||||
* A larger (IPv6) message may be fragmented and sent as multiple MAC frames. The message
|
||||
* transmission is considered a failure, if any of its fragments fail after all MAC retry
|
||||
* attempts.
|
||||
*
|
||||
*/
|
||||
void AddMessageTxStatus(bool aTxStatus) {
|
||||
mMessageErrorRate.AddSample(aTxStatus, OPENTHREAD_CONFIG_IPV6_TX_ERR_RATE_AVERAGING_WINDOW);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the MAC frame transmission error rate for the link.
|
||||
*
|
||||
* The rate is maintained over a window of (roughly) last `OPENTHREAD_CONFIG_FRAME_TX_ERR_RATE_AVERAGING_WINDOW`
|
||||
* frame transmissions.
|
||||
*
|
||||
* @returns The error rate with maximum value `0xffff` corresponding to 100% failure rate.
|
||||
*
|
||||
*/
|
||||
uint16_t GetFrameErrorRate(void) const { return mFrameErrorRate.GetFailureRate(); }
|
||||
|
||||
/**
|
||||
* This method returns the message error rate for the link.
|
||||
*
|
||||
* The rate is maintained over a window of (roughly) last `OPENTHREAD_CONFIG_IPV6_TX_ERR_RATE_AVERAGING_WINDOW`
|
||||
* (IPv6) messages.
|
||||
*
|
||||
* Note that a larger (IPv6) message can be fragmented and sent as multiple MAC frames. The message transmission is
|
||||
* considered a failure, if any of its fragments fail after all MAC retry attempts.
|
||||
*
|
||||
* @returns The error rate with maximum value `0xffff` corresponding to 100% failure rate.
|
||||
*
|
||||
*/
|
||||
uint16_t GetMessageErrorRate(void) const { return mMessageErrorRate.GetFailureRate(); }
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
|
||||
|
||||
/**
|
||||
* This method converts a received signal strength value to a link margin value.
|
||||
*
|
||||
@@ -366,22 +415,22 @@ private:
|
||||
{
|
||||
// Constants for obtaining link quality from link margin:
|
||||
|
||||
kThreshold3 = 20, // Link margin threshold for quality 3 link.
|
||||
kThreshold2 = 10, // Link margin threshold for quality 2 link.
|
||||
kThreshold1 = 2, // Link margin threshold for quality 1 link.
|
||||
kHysteresisThreshold = 2, // Link margin hysteresis threshold.
|
||||
kThreshold3 = 20, ///< Link margin threshold for quality 3 link.
|
||||
kThreshold2 = 10, ///< Link margin threshold for quality 2 link.
|
||||
kThreshold1 = 2, ///< Link margin threshold for quality 1 link.
|
||||
kHysteresisThreshold = 2, ///< Link margin hysteresis threshold.
|
||||
|
||||
// constants for test:
|
||||
|
||||
kLinkQuality3LinkMargin = 50, ///< link margin for Link Quality 3 (21 - 255)
|
||||
kLinkQuality2LinkMargin = 15, ///< link margin for Link Quality 3 (21 - 255)
|
||||
kLinkQuality1LinkMargin = 5, ///< link margin for Link Quality 3 (21 - 255)
|
||||
kLinkQuality0LinkMargin = 0, ///< link margin for Link Quality 3 (21 - 255)
|
||||
kLinkQuality3LinkMargin = 50, ///< link margin for Link Quality 3 (21 - 255)
|
||||
kLinkQuality2LinkMargin = 15, ///< link margin for Link Quality 3 (21 - 255)
|
||||
kLinkQuality1LinkMargin = 5, ///< link margin for Link Quality 3 (21 - 255)
|
||||
kLinkQuality0LinkMargin = 0, ///< link margin for Link Quality 3 (21 - 255)
|
||||
|
||||
kNoLinkQuality = 0xff, // Used to indicate that there is no previous/last link quality.
|
||||
};
|
||||
|
||||
void SetLinkQuality(uint8_t aLinkQuality) { mRssAverager.mLinkQuality = aLinkQuality; }
|
||||
void SetLinkQuality(uint8_t aLinkQuality) { mLinkQuality = aLinkQuality; }
|
||||
|
||||
/* Static private method to calculate the link quality from a given link margin while taking into account the last
|
||||
* link quality value and adding the hysteresis value to the thresholds. If there is no previous value for link
|
||||
@@ -391,7 +440,12 @@ private:
|
||||
static uint8_t CalculateLinkQuality(uint8_t aLinkMargin, uint8_t aLastLinkQuality);
|
||||
|
||||
RssAverager mRssAverager;
|
||||
uint8_t mLinkQuality;
|
||||
int8_t mLastRss;
|
||||
#if OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
|
||||
SuccessRateTracker mFrameErrorRate;
|
||||
SuccessRateTracker mMessageErrorRate;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -187,6 +187,11 @@ void MeshForwarder::ScheduleTransmissionTask(void)
|
||||
|
||||
if ((mSendMessage = GetDirectTransmission()) != NULL)
|
||||
{
|
||||
if (mSendMessage->GetOffset() == 0)
|
||||
{
|
||||
mSendMessage->SetTxSuccess(true);
|
||||
}
|
||||
|
||||
mSendMessageMaxMacTxAttempts = Mac::kDirectFrameMacTxAttempts;
|
||||
GetNetif().GetMac().SendFrameRequest(mMacSender);
|
||||
ExitNow();
|
||||
@@ -962,18 +967,22 @@ void MeshForwarder::HandleSentFrame(Mac::Frame &aFrame, otError aError)
|
||||
|
||||
if (mSendMessage->GetDirectTransmission())
|
||||
{
|
||||
if (aError != OT_ERROR_NONE)
|
||||
{
|
||||
// If the transmission of any fragment frame fails,
|
||||
// the overall message transmission is considered
|
||||
// as failed
|
||||
|
||||
mSendMessage->SetTxSuccess(false);
|
||||
|
||||
#if OPENTHREAD_CONFIG_DROP_MESSAGE_ON_FRAGMENT_TX_FAILURE
|
||||
|
||||
if (aError != OT_ERROR_NONE)
|
||||
{
|
||||
// We set the NextOffset to end of message to avoid sending
|
||||
// any remaining fragments in the message.
|
||||
|
||||
mMessageNextOffset = mSendMessage->GetLength();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mMessageNextOffset < mSendMessage->GetLength())
|
||||
{
|
||||
@@ -983,6 +992,11 @@ void MeshForwarder::HandleSentFrame(Mac::Frame &aFrame, otError aError)
|
||||
{
|
||||
mSendMessage->ClearDirectTransmission();
|
||||
mSendMessage->SetOffset(0);
|
||||
|
||||
if (neighbor != NULL)
|
||||
{
|
||||
neighbor->GetLinkInfo().AddMessageTxStatus(mSendMessage->GetTxSuccess());
|
||||
}
|
||||
}
|
||||
|
||||
if (mSendMessage->GetSubType() == Message::kSubTypeMleDiscoverRequest)
|
||||
|
||||
@@ -477,6 +477,7 @@ Message *MeshForwarder::GetIndirectTransmission(Child &aChild)
|
||||
aChild.SetIndirectMessage(message);
|
||||
aChild.SetIndirectFragmentOffset(0);
|
||||
aChild.ResetIndirectTxAttempts();
|
||||
aChild.SetIndirectTxSuccess(true);
|
||||
|
||||
if (message != NULL)
|
||||
{
|
||||
@@ -644,6 +645,7 @@ void MeshForwarder::HandleSentFrameToChild(const Mac::Frame &aFrame, otError aEr
|
||||
}
|
||||
|
||||
child->ResetIndirectTxAttempts();
|
||||
child->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
|
||||
@@ -670,6 +672,7 @@ void MeshForwarder::HandleSentFrameToChild(const Mac::Frame &aFrame, otError aEr
|
||||
{
|
||||
child->SetIndirectFragmentOffset(0);
|
||||
child->SetIndirectMessage(NULL);
|
||||
child->GetLinkInfo().AddMessageTxStatus(child->GetIndirectTxSuccess());
|
||||
|
||||
// Enable short source address matching after the first indirect
|
||||
// message transmission attempt to the child. We intentionally do
|
||||
|
||||
@@ -3949,11 +3949,16 @@ otError MleRouter::GetChildInfo(Child &aChild, otChildInfo &aChildInfo)
|
||||
aChildInfo.mAverageRssi = aChild.GetLinkInfo().GetAverageRss();
|
||||
aChildInfo.mLastRssi = aChild.GetLinkInfo().GetLastRss();
|
||||
|
||||
aChildInfo.mRxOnWhenIdle = aChild.IsRxOnWhenIdle();
|
||||
aChildInfo.mSecureDataRequest = aChild.IsSecureDataRequest();
|
||||
aChildInfo.mFullFunction = aChild.IsFullThreadDevice();
|
||||
aChildInfo.mFullNetworkData = aChild.IsFullNetworkData();
|
||||
aChildInfo.mIsStateRestoring = aChild.IsStateRestoring();
|
||||
#if OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
|
||||
aChildInfo.mFrameErrorRate = aChild.GetLinkInfo().GetFrameErrorRate();
|
||||
aChildInfo.mMessageErrorRate = aChild.GetLinkInfo().GetMessageErrorRate();
|
||||
#endif
|
||||
|
||||
aChildInfo.mRxOnWhenIdle = aChild.IsRxOnWhenIdle();
|
||||
aChildInfo.mSecureDataRequest = aChild.IsSecureDataRequest();
|
||||
aChildInfo.mFullFunction = aChild.IsFullThreadDevice();
|
||||
aChildInfo.mFullNetworkData = aChild.IsFullNetworkData();
|
||||
aChildInfo.mIsStateRestoring = aChild.IsStateRestoring();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -4049,6 +4054,10 @@ exit:
|
||||
aNeighInfo.mLinkQualityIn = neighbor->GetLinkInfo().GetLinkQuality();
|
||||
aNeighInfo.mAverageRssi = neighbor->GetLinkInfo().GetAverageRss();
|
||||
aNeighInfo.mLastRssi = neighbor->GetLinkInfo().GetLastRss();
|
||||
#if OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
|
||||
aNeighInfo.mFrameErrorRate = neighbor->GetLinkInfo().GetFrameErrorRate();
|
||||
aNeighInfo.mMessageErrorRate = neighbor->GetLinkInfo().GetMessageErrorRate();
|
||||
#endif
|
||||
aNeighInfo.mRxOnWhenIdle = neighbor->IsRxOnWhenIdle();
|
||||
aNeighInfo.mSecureDataRequest = neighbor->IsSecureDataRequest();
|
||||
aNeighInfo.mFullFunction = neighbor->IsFullThreadDevice();
|
||||
|
||||
@@ -585,6 +585,22 @@ public:
|
||||
*/
|
||||
void SetIndirectFragmentOffset(uint16_t aFragmentOffset) { mIndirectFragmentOffset = aFragmentOffset; }
|
||||
|
||||
/**
|
||||
* This method gets the transmission status (success/failure) of the indirect transmission.
|
||||
*
|
||||
* @returns The transmission status of indirect transmission, `true` indicating success, `false` indicating failure.
|
||||
*
|
||||
*/
|
||||
bool GetIndirectTxSuccess(void) const { return mIndirectTxSuccess; }
|
||||
|
||||
/**
|
||||
* This method sets the transmission status (success/failure) of the indirect transmission.
|
||||
*
|
||||
* @param[in] aTxStatus The transmission status, `true` indicating success, `false` indicating failure.
|
||||
*
|
||||
*/
|
||||
void SetIndirectTxSuccess(bool aTxStatus) { mIndirectTxSuccess = aTxStatus; }
|
||||
|
||||
/**
|
||||
* This method gets the IEEE 802.15.4 Key ID to use for indirect retransmissions.
|
||||
*
|
||||
@@ -778,7 +794,8 @@ private:
|
||||
|
||||
uint32_t mIndirectFrameCounter; ///< Frame counter for current indirect message (used fore retx).
|
||||
Message *mIndirectMessage; ///< Current indirect message.
|
||||
uint16_t mIndirectFragmentOffset; ///< 6LoWPAN fragment offset for the indirect message.
|
||||
uint16_t mIndirectFragmentOffset : 15; ///< 6LoWPAN fragment offset for the indirect message.
|
||||
bool mIndirectTxSuccess : 1; ///< Indicates tx success/failure of current indirect message.
|
||||
uint8_t mIndirectKeyId; ///< Key Id for current indirect message (used for retx).
|
||||
uint8_t mIndirectTxAttempts; ///< Number of data poll triggered tx attempts.
|
||||
uint8_t mIndirectDsn; ///< MAC level Data Sequence Number (DSN) for retx attempts.
|
||||
|
||||
Reference in New Issue
Block a user