mirror of
https://github.com/espressif/openthread.git
synced 2026-07-07 12:52:35 +00:00
add mac layer counter (#90)
* add mac layer counter * add more counters and Doxygen for MAC counters * have a seperate counter for acked data transmission and refine the code based on the comments * refine counters for acked and unacked transmissions * fix check test error * refine code style and use VerifyOrExit to exit * move all events tracker to tx/rx done task, and add more counters * fix other error counter * refine counters structure to be clearer * add Doxygen for the added thread errors * fix conflicts
This commit is contained in:
@@ -81,6 +81,36 @@ typedef enum ThreadError
|
||||
*/
|
||||
kThreadError_Detached = 18,
|
||||
|
||||
/**
|
||||
* FCS check failure while receiving.
|
||||
*/
|
||||
kThreadError_FcsErr = 19,
|
||||
|
||||
/**
|
||||
* No frame received.
|
||||
*/
|
||||
kThreadError_NoFrameReceived = 20,
|
||||
|
||||
/**
|
||||
* Received a frame from an unknown neighbor.
|
||||
*/
|
||||
kThreadError_UnknownNeighbor = 21,
|
||||
|
||||
/**
|
||||
* Received a frame from an invalid source address.
|
||||
*/
|
||||
kThreadError_InvalidSourceAddress = 22,
|
||||
|
||||
/**
|
||||
* Received a frame filtered by the whitelist.
|
||||
*/
|
||||
kThreadError_WhitelistFiltered = 23,
|
||||
|
||||
/**
|
||||
* Received a frame filtered by the destination address check.
|
||||
*/
|
||||
kThreadError_DestinationAddressFiltered = 24,
|
||||
|
||||
kThreadError_Error = 255,
|
||||
} ThreadError;
|
||||
|
||||
@@ -341,6 +371,38 @@ typedef enum
|
||||
kDeviceRoleLeader, ///< The Thread Leader role.
|
||||
} otDeviceRole;
|
||||
|
||||
/**
|
||||
* This structure represents the MAC layer counters.
|
||||
*/
|
||||
typedef struct otMacCounters
|
||||
{
|
||||
uint32_t mTxTotal; ///< The total number of transmissions.
|
||||
uint32_t mTxAckRequested; ///< The number of transmissions with ack request.
|
||||
uint32_t mTxAcked; ///< The number of transmissions that were acked.
|
||||
uint32_t mTxNoAckRequested; ///< The number of transmissions without ack request.
|
||||
uint32_t mTxData; ///< The number of transmitted data.
|
||||
uint32_t mTxDataPoll; ///< The number of transmitted data poll.
|
||||
uint32_t mTxBeacon; ///< The number of transmitted beacon.
|
||||
uint32_t mTxBeaconRequest; ///< The number of transmitted beacon request.
|
||||
uint32_t mTxOther; ///< The number of transmitted other types of frames.
|
||||
uint32_t mTxRetry; ///< The number of retransmission times.
|
||||
uint32_t mTxErrCca; ///< The number of CCA failure times.
|
||||
uint32_t mRxTotal; ///< The total number of received packets.
|
||||
uint32_t mRxData; ///< The number of received data.
|
||||
uint32_t mRxDataPoll; ///< The number of received data poll.
|
||||
uint32_t mRxBeacon; ///< The number of received beacon.
|
||||
uint32_t mRxBeaconRequest; ///< The number of received beacon request.
|
||||
uint32_t mRxOther; ///< The number of received other types of frames.
|
||||
uint32_t mRxWhitelistFiltered; ///< The number of received packets filtered by whitelist.
|
||||
uint32_t mRxDestAddrFiltered; ///< The number of received packets filtered by destination check.
|
||||
uint32_t mRxErrNoFrame; ///< The number of received packets that do not contain contents.
|
||||
uint32_t mRxErrUnknownNeighbor; ///< The number of recevied packets from unknown neighbor.
|
||||
uint32_t mRxErrInvalidSrcAddr; ///< The number of received packets whose source address is invalid.
|
||||
uint32_t mRxErrSec; ///< The number of recevied packets with security error.
|
||||
uint32_t mRxErrFcs; ///< The number of recevied packets with FCS error.
|
||||
uint32_t mRxErrOther; ///< The number of received packets with other error.
|
||||
} otMacCounters;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -901,6 +901,13 @@ bool otIsLinkPromiscuous(void);
|
||||
*/
|
||||
ThreadError otSetLinkPromiscuous(bool aPromiscuous);
|
||||
|
||||
/**
|
||||
* Get the MAC layer counters.
|
||||
*
|
||||
* @returns A pointer to the MAC layer counters.
|
||||
*/
|
||||
const otMacCounters *otGetMacCounters(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -52,6 +52,7 @@ const struct Command Interpreter::sCommands[] =
|
||||
{ "channel", &ProcessChannel },
|
||||
{ "childtimeout", &ProcessChildTimeout },
|
||||
{ "contextreusedelay", &ProcessContextIdReuseDelay },
|
||||
{ "counter", &ProcessCounters },
|
||||
{ "extaddr", &ProcessExtAddress },
|
||||
{ "extpanid", &ProcessExtPanId },
|
||||
{ "ipaddr", &ProcessIpAddr },
|
||||
@@ -217,6 +218,47 @@ exit:
|
||||
AppendResult(error);
|
||||
}
|
||||
|
||||
void Interpreter::ProcessCounters(int argc, char *argv[])
|
||||
{
|
||||
if (argc == 0)
|
||||
{
|
||||
sServer->OutputFormat("mac\r\n");
|
||||
sServer->OutputFormat("Done\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp(argv[0], "mac") == 0)
|
||||
{
|
||||
const otMacCounters *counters = otGetMacCounters();
|
||||
sServer->OutputFormat("TxTotal: %d\r\n", counters->mTxTotal);
|
||||
sServer->OutputFormat(" TxAckRequested: %d\r\n", counters->mTxAckRequested);
|
||||
sServer->OutputFormat(" TxAcked: %d\r\n", counters->mTxAcked);
|
||||
sServer->OutputFormat(" TxNoAckRequested: %d\r\n", counters->mTxNoAckRequested);
|
||||
sServer->OutputFormat(" TxData: %d\r\n", counters->mTxData);
|
||||
sServer->OutputFormat(" TxDataPoll: %d\r\n", counters->mTxDataPoll);
|
||||
sServer->OutputFormat(" TxBeacon: %d\r\n", counters->mTxBeacon);
|
||||
sServer->OutputFormat(" TxBeaconRequest: %d\r\n", counters->mTxBeaconRequest);
|
||||
sServer->OutputFormat(" TxOther: %d\r\n", counters->mTxOther);
|
||||
sServer->OutputFormat(" TxRetry: %d\r\n", counters->mTxRetry);
|
||||
sServer->OutputFormat(" TxErrCca: %d\r\n", counters->mTxErrCca);
|
||||
sServer->OutputFormat("RxTotal: %d\r\n", counters->mRxTotal);
|
||||
sServer->OutputFormat(" RxData: %d\r\n", counters->mRxData);
|
||||
sServer->OutputFormat(" RxDataPoll: %d\r\n", counters->mRxDataPoll);
|
||||
sServer->OutputFormat(" RxBeacon: %d\r\n", counters->mRxBeacon);
|
||||
sServer->OutputFormat(" RxBeaconRequest: %d\r\n", counters->mRxBeaconRequest);
|
||||
sServer->OutputFormat(" RxOther: %d\r\n", counters->mRxOther);
|
||||
sServer->OutputFormat(" RxWhitelistFiltered: %d\r\n", counters->mRxWhitelistFiltered);
|
||||
sServer->OutputFormat(" RxDestAddrFiltered: %d\r\n", counters->mRxDestAddrFiltered);
|
||||
sServer->OutputFormat(" RxErrNoFrame: %d\r\n", counters->mRxErrNoFrame);
|
||||
sServer->OutputFormat(" RxErrNoUnknownNeighbor: %d\r\n", counters->mRxErrUnknownNeighbor);
|
||||
sServer->OutputFormat(" RxErrInvalidSrcAddr: %d\r\n", counters->mRxErrInvalidSrcAddr);
|
||||
sServer->OutputFormat(" RxErrSec: %d\r\n", counters->mRxErrSec);
|
||||
sServer->OutputFormat(" RxErrFcs: %d\r\n", counters->mRxErrFcs);
|
||||
sServer->OutputFormat(" RxErrOther: %d\r\n", counters->mRxErrOther);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::ProcessExtAddress(int argc, char *argv[])
|
||||
{
|
||||
const uint8_t *extAddress = otGetExtendedAddress();
|
||||
|
||||
@@ -89,6 +89,7 @@ private:
|
||||
static void ProcessChannel(int argc, char *argv[]);
|
||||
static void ProcessChildTimeout(int argc, char *argv[]);
|
||||
static void ProcessContextIdReuseDelay(int argc, char *argv[]);
|
||||
static void ProcessCounters(int argc, char *argv[]);
|
||||
static void ProcessExtAddress(int argc, char *argv[]);
|
||||
static void ProcessExtPanId(int argc, char *argv[]);
|
||||
static void ProcessIpAddr(int argc, char *argv[]);
|
||||
|
||||
+154
-36
@@ -105,6 +105,8 @@ Mac::Mac(ThreadNetif &aThreadNetif):
|
||||
mExtAddress.m8[i] = otPlatRandomGet();
|
||||
}
|
||||
|
||||
memset(&mCounters, 0, sizeof(otMacCounters));
|
||||
|
||||
SetExtendedPanId(sExtendedPanidInit);
|
||||
SetNetworkName(sNetworkNameInit);
|
||||
SetPanId(kPanIdBroadcast);
|
||||
@@ -486,11 +488,16 @@ void Mac::TransmitDoneTask(bool aRxPending, ThreadError aError)
|
||||
{
|
||||
mAckTimer.Stop();
|
||||
|
||||
mCounters.mTxTotal++;
|
||||
|
||||
if (aError == kThreadError_ChannelAccessFailure &&
|
||||
mCsmaAttempts < kMaxCSMABackoffs)
|
||||
{
|
||||
mCsmaAttempts++;
|
||||
StartCsmaBackoff();
|
||||
|
||||
mCounters.mTxErrCca++;
|
||||
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
@@ -498,14 +505,6 @@ void Mac::TransmitDoneTask(bool aRxPending, ThreadError aError)
|
||||
|
||||
switch (mState)
|
||||
{
|
||||
case kStateActiveScan:
|
||||
mAckTimer.Start(mScanDuration);
|
||||
break;
|
||||
|
||||
case kStateTransmitBeacon:
|
||||
SentFrame(true);
|
||||
break;
|
||||
|
||||
case kStateTransmitData:
|
||||
if (aRxPending)
|
||||
{
|
||||
@@ -516,6 +515,8 @@ void Mac::TransmitDoneTask(bool aRxPending, ThreadError aError)
|
||||
mReceiveTimer.Stop();
|
||||
}
|
||||
|
||||
case kStateActiveScan:
|
||||
case kStateTransmitBeacon:
|
||||
SentFrame(aError == kThreadError_None);
|
||||
break;
|
||||
|
||||
@@ -560,6 +561,7 @@ void Mac::HandleAckTimer(void)
|
||||
|
||||
case kStateTransmitData:
|
||||
otLogDebgMac("ack timer fired\n");
|
||||
mCounters.mTxTotal++;
|
||||
SentFrame(false);
|
||||
break;
|
||||
|
||||
@@ -591,37 +593,65 @@ void Mac::SentFrame(bool aAcked)
|
||||
Neighbor *neighbor;
|
||||
Sender *sender;
|
||||
|
||||
if (sendFrame.GetAckRequest() && !aAcked)
|
||||
{
|
||||
otDumpDebgMac("NO ACK", sendFrame.GetHeader(), 16);
|
||||
|
||||
if (mTransmitAttempts < kMaxFrameAttempts)
|
||||
{
|
||||
mTransmitAttempts++;
|
||||
StartCsmaBackoff();
|
||||
|
||||
mCounters.mTxRetry++;
|
||||
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
sendFrame.GetDstAddr(destination);
|
||||
|
||||
if ((neighbor = mMle.GetNeighbor(destination)) != NULL)
|
||||
{
|
||||
neighbor->mState = Neighbor::kStateInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
mTransmitAttempts = 0;
|
||||
|
||||
if (sendFrame.GetAckRequest())
|
||||
{
|
||||
mCounters.mTxAckRequested++;
|
||||
|
||||
if (aAcked)
|
||||
{
|
||||
mCounters.mTxAcked++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mCounters.mTxNoAckRequested++;
|
||||
}
|
||||
|
||||
switch (mState)
|
||||
{
|
||||
case kStateActiveScan:
|
||||
mCounters.mTxBeaconRequest++;
|
||||
mAckTimer.Start(mScanDuration);
|
||||
break;
|
||||
|
||||
case kStateTransmitBeacon:
|
||||
mCounters.mTxBeacon++;
|
||||
ScheduleNextTransmission();
|
||||
break;
|
||||
|
||||
case kStateTransmitData:
|
||||
if (sendFrame.GetAckRequest() && !aAcked)
|
||||
if (mReceiveTimer.IsRunning())
|
||||
{
|
||||
otDumpDebgMac("NO ACK", sendFrame.GetHeader(), 16);
|
||||
|
||||
if (mTransmitAttempts < kMaxFrameAttempts)
|
||||
{
|
||||
mTransmitAttempts++;
|
||||
StartCsmaBackoff();
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
sendFrame.GetDstAddr(destination);
|
||||
|
||||
if ((neighbor = mMle.GetNeighbor(destination)) != NULL)
|
||||
{
|
||||
neighbor->mState = Neighbor::kStateInvalid;
|
||||
}
|
||||
mCounters.mTxDataPoll++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCounters.mTxData++;
|
||||
}
|
||||
|
||||
mTransmitAttempts = 0;
|
||||
|
||||
sender = mSendHead;
|
||||
mSendHead = mSendHead->mNext;
|
||||
@@ -750,8 +780,12 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
|
||||
Neighbor *neighbor;
|
||||
Whitelist::Entry *entry;
|
||||
int8_t rssi;
|
||||
ThreadError error = aError;
|
||||
|
||||
VerifyOrExit(aError == kThreadError_None && aFrame != NULL, ;);
|
||||
mCounters.mRxTotal++;
|
||||
|
||||
VerifyOrExit(error == kThreadError_None, ;);
|
||||
VerifyOrExit(aFrame != NULL, error = kThreadError_NoFrameReceived);
|
||||
|
||||
aFrame->mSecurityValid = false;
|
||||
|
||||
@@ -769,7 +803,12 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
|
||||
break;
|
||||
|
||||
case sizeof(ShortAddress):
|
||||
VerifyOrExit(neighbor != NULL, otLogDebgMac("drop not neighbor\n"));
|
||||
if (neighbor == NULL)
|
||||
{
|
||||
otLogDebgMac("drop not neighbor\n");
|
||||
ExitNow(error = kThreadError_UnknownNeighbor);
|
||||
}
|
||||
|
||||
srcaddr.mLength = sizeof(srcaddr.mExtAddress);
|
||||
memcpy(&srcaddr.mExtAddress, &neighbor->mMacAddr, sizeof(srcaddr.mExtAddress));
|
||||
break;
|
||||
@@ -778,13 +817,13 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow();
|
||||
ExitNow(error = kThreadError_InvalidSourceAddress);
|
||||
}
|
||||
|
||||
// Source Whitelist Processing
|
||||
if (srcaddr.mLength != 0 && mWhitelist.IsEnabled())
|
||||
{
|
||||
VerifyOrExit((entry = mWhitelist.Find(srcaddr.mExtAddress)) != NULL, ;);
|
||||
VerifyOrExit((entry = mWhitelist.Find(srcaddr.mExtAddress)) != NULL, error = kThreadError_WhitelistFiltered);
|
||||
|
||||
if (mWhitelist.GetConstantRssi(*entry, rssi) == kThreadError_None)
|
||||
{
|
||||
@@ -804,26 +843,32 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
|
||||
aFrame->GetDstPanId(panid);
|
||||
VerifyOrExit((panid == kShortAddrBroadcast || panid == mPanId) &&
|
||||
((mRxOnWhenIdle && dstaddr.mShortAddress == kShortAddrBroadcast) ||
|
||||
dstaddr.mShortAddress == mShortAddress), ;);
|
||||
dstaddr.mShortAddress == mShortAddress), error = kThreadError_DestinationAddressFiltered);
|
||||
break;
|
||||
|
||||
case sizeof(ExtAddress):
|
||||
aFrame->GetDstPanId(panid);
|
||||
VerifyOrExit(panid == mPanId &&
|
||||
memcmp(&dstaddr.mExtAddress, &mExtAddress, sizeof(dstaddr.mExtAddress)) == 0, ;);
|
||||
memcmp(&dstaddr.mExtAddress, &mExtAddress, sizeof(dstaddr.mExtAddress)) == 0,
|
||||
error = kThreadError_DestinationAddressFiltered);
|
||||
break;
|
||||
}
|
||||
|
||||
// Security Processing
|
||||
SuccessOrExit(ProcessReceiveSecurity(*aFrame, srcaddr, neighbor));
|
||||
SuccessOrExit(error = ProcessReceiveSecurity(*aFrame, srcaddr, neighbor));
|
||||
|
||||
switch (mState)
|
||||
{
|
||||
case kStateActiveScan:
|
||||
if (aFrame->GetType() == Frame::kFcfFrameBeacon)
|
||||
{
|
||||
mCounters.mRxBeacon++;
|
||||
mActiveScanHandler(mActiveScanContext, aFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCounters.mRxOther++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -833,9 +878,27 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
|
||||
mReceiveTimer.Stop();
|
||||
}
|
||||
|
||||
if (aFrame->GetType() == Frame::kFcfFrameMacCmd)
|
||||
switch (aFrame->GetType())
|
||||
{
|
||||
SuccessOrExit(HandleMacCommand(*aFrame));
|
||||
case Frame::kFcfFrameMacCmd:
|
||||
if (HandleMacCommand(*aFrame) == kThreadError_Drop)
|
||||
{
|
||||
ExitNow(error = kThreadError_None);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Frame::kFcfFrameBeacon:
|
||||
mCounters.mRxBeacon++;
|
||||
break;
|
||||
|
||||
case Frame::kFcfFrameData:
|
||||
mCounters.mRxData++;
|
||||
break;
|
||||
|
||||
default:
|
||||
mCounters.mRxOther++;
|
||||
break;
|
||||
}
|
||||
|
||||
for (Receiver *receiver = mReceiveHead; receiver; receiver = receiver->mNext)
|
||||
@@ -847,6 +910,45 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case kThreadError_Security:
|
||||
mCounters.mRxErrSec++;
|
||||
break;
|
||||
|
||||
case kThreadError_FcsErr:
|
||||
mCounters.mRxErrFcs++;
|
||||
break;
|
||||
|
||||
case kThreadError_NoFrameReceived:
|
||||
mCounters.mRxErrNoFrame++;
|
||||
break;
|
||||
|
||||
case kThreadError_UnknownNeighbor:
|
||||
mCounters.mRxErrUnknownNeighbor++;
|
||||
break;
|
||||
|
||||
case kThreadError_InvalidSourceAddress:
|
||||
mCounters.mRxErrInvalidSrcAddr++;
|
||||
break;
|
||||
|
||||
case kThreadError_WhitelistFiltered:
|
||||
mCounters.mRxWhitelistFiltered++;
|
||||
break;
|
||||
|
||||
case kThreadError_DestinationAddressFiltered:
|
||||
mCounters.mRxDestAddrFiltered++;
|
||||
break;
|
||||
|
||||
default:
|
||||
mCounters.mRxErrOther++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NextOperation();
|
||||
}
|
||||
|
||||
@@ -857,9 +959,12 @@ ThreadError Mac::HandleMacCommand(Frame &aFrame)
|
||||
|
||||
aFrame.GetCommandId(commandId);
|
||||
|
||||
if (commandId == Frame::kMacCmdBeaconRequest)
|
||||
switch (commandId)
|
||||
{
|
||||
case Frame::kMacCmdBeaconRequest:
|
||||
mCounters.mRxBeaconRequest++;
|
||||
otLogInfoMac("Received Beacon Request\n");
|
||||
|
||||
mTransmitBeacon = true;
|
||||
|
||||
if (mState == kStateIdle)
|
||||
@@ -870,6 +975,14 @@ ThreadError Mac::HandleMacCommand(Frame &aFrame)
|
||||
}
|
||||
|
||||
ExitNow(error = kThreadError_Drop);
|
||||
|
||||
case Frame::kMacCmdDataRequest:
|
||||
mCounters.mRxDataPoll++;
|
||||
break;
|
||||
|
||||
default:
|
||||
mCounters.mRxOther++;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -902,5 +1015,10 @@ Whitelist &Mac::GetWhitelist(void)
|
||||
return mWhitelist;
|
||||
}
|
||||
|
||||
otMacCounters &Mac::GetCounters(void)
|
||||
{
|
||||
return mCounters;
|
||||
}
|
||||
|
||||
} // namespace Mac
|
||||
} // namespace Thread
|
||||
|
||||
@@ -419,6 +419,14 @@ public:
|
||||
*/
|
||||
void SetPromiscuous(bool aPromiscuous);
|
||||
|
||||
/**
|
||||
* This method returns the MAC counter.
|
||||
*
|
||||
* @returns A reference to the MAC counter.
|
||||
*
|
||||
*/
|
||||
otMacCounters &GetCounters(void);
|
||||
|
||||
private:
|
||||
void GenerateNonce(const ExtAddress &aAddress, uint32_t aFrameCounter, uint8_t aSecurityLevel, uint8_t *aNonce);
|
||||
void NextOperation(void);
|
||||
@@ -484,6 +492,8 @@ private:
|
||||
otLinkPcapCallback mPcapCallback;
|
||||
|
||||
Whitelist mWhitelist;
|
||||
|
||||
otMacCounters mCounters;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -515,6 +515,11 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
const otMacCounters *otGetMacCounters(void)
|
||||
{
|
||||
return &sThreadNetif->GetMac().GetCounters();
|
||||
}
|
||||
|
||||
bool otIsIp6AddressEqual(const otIp6Address *a, const otIp6Address *b)
|
||||
{
|
||||
return *static_cast<const Ip6::Address *>(a) == *static_cast<const Ip6::Address *>(b);
|
||||
|
||||
Reference in New Issue
Block a user