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:
Lu Wang
2016-06-12 00:32:51 -07:00
committed by Jonathan Hui
parent 3576322262
commit 9a7fa9b80e
7 changed files with 281 additions and 36 deletions
+62
View File
@@ -81,6 +81,36 @@ typedef enum ThreadError
*/ */
kThreadError_Detached = 18, 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, kThreadError_Error = 255,
} ThreadError; } ThreadError;
@@ -341,6 +371,38 @@ typedef enum
kDeviceRoleLeader, ///< The Thread Leader role. kDeviceRoleLeader, ///< The Thread Leader role.
} otDeviceRole; } 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;
/** /**
* @} * @}
* *
+7
View File
@@ -901,6 +901,13 @@ bool otIsLinkPromiscuous(void);
*/ */
ThreadError otSetLinkPromiscuous(bool aPromiscuous); ThreadError otSetLinkPromiscuous(bool aPromiscuous);
/**
* Get the MAC layer counters.
*
* @returns A pointer to the MAC layer counters.
*/
const otMacCounters *otGetMacCounters(void);
/** /**
* @} * @}
* *
+42
View File
@@ -52,6 +52,7 @@ const struct Command Interpreter::sCommands[] =
{ "channel", &ProcessChannel }, { "channel", &ProcessChannel },
{ "childtimeout", &ProcessChildTimeout }, { "childtimeout", &ProcessChildTimeout },
{ "contextreusedelay", &ProcessContextIdReuseDelay }, { "contextreusedelay", &ProcessContextIdReuseDelay },
{ "counter", &ProcessCounters },
{ "extaddr", &ProcessExtAddress }, { "extaddr", &ProcessExtAddress },
{ "extpanid", &ProcessExtPanId }, { "extpanid", &ProcessExtPanId },
{ "ipaddr", &ProcessIpAddr }, { "ipaddr", &ProcessIpAddr },
@@ -217,6 +218,47 @@ exit:
AppendResult(error); 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[]) void Interpreter::ProcessExtAddress(int argc, char *argv[])
{ {
const uint8_t *extAddress = otGetExtendedAddress(); const uint8_t *extAddress = otGetExtendedAddress();
+1
View File
@@ -89,6 +89,7 @@ private:
static void ProcessChannel(int argc, char *argv[]); static void ProcessChannel(int argc, char *argv[]);
static void ProcessChildTimeout(int argc, char *argv[]); static void ProcessChildTimeout(int argc, char *argv[]);
static void ProcessContextIdReuseDelay(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 ProcessExtAddress(int argc, char *argv[]);
static void ProcessExtPanId(int argc, char *argv[]); static void ProcessExtPanId(int argc, char *argv[]);
static void ProcessIpAddr(int argc, char *argv[]); static void ProcessIpAddr(int argc, char *argv[]);
+154 -36
View File
@@ -105,6 +105,8 @@ Mac::Mac(ThreadNetif &aThreadNetif):
mExtAddress.m8[i] = otPlatRandomGet(); mExtAddress.m8[i] = otPlatRandomGet();
} }
memset(&mCounters, 0, sizeof(otMacCounters));
SetExtendedPanId(sExtendedPanidInit); SetExtendedPanId(sExtendedPanidInit);
SetNetworkName(sNetworkNameInit); SetNetworkName(sNetworkNameInit);
SetPanId(kPanIdBroadcast); SetPanId(kPanIdBroadcast);
@@ -486,11 +488,16 @@ void Mac::TransmitDoneTask(bool aRxPending, ThreadError aError)
{ {
mAckTimer.Stop(); mAckTimer.Stop();
mCounters.mTxTotal++;
if (aError == kThreadError_ChannelAccessFailure && if (aError == kThreadError_ChannelAccessFailure &&
mCsmaAttempts < kMaxCSMABackoffs) mCsmaAttempts < kMaxCSMABackoffs)
{ {
mCsmaAttempts++; mCsmaAttempts++;
StartCsmaBackoff(); StartCsmaBackoff();
mCounters.mTxErrCca++;
ExitNow(); ExitNow();
} }
@@ -498,14 +505,6 @@ void Mac::TransmitDoneTask(bool aRxPending, ThreadError aError)
switch (mState) switch (mState)
{ {
case kStateActiveScan:
mAckTimer.Start(mScanDuration);
break;
case kStateTransmitBeacon:
SentFrame(true);
break;
case kStateTransmitData: case kStateTransmitData:
if (aRxPending) if (aRxPending)
{ {
@@ -516,6 +515,8 @@ void Mac::TransmitDoneTask(bool aRxPending, ThreadError aError)
mReceiveTimer.Stop(); mReceiveTimer.Stop();
} }
case kStateActiveScan:
case kStateTransmitBeacon:
SentFrame(aError == kThreadError_None); SentFrame(aError == kThreadError_None);
break; break;
@@ -560,6 +561,7 @@ void Mac::HandleAckTimer(void)
case kStateTransmitData: case kStateTransmitData:
otLogDebgMac("ack timer fired\n"); otLogDebgMac("ack timer fired\n");
mCounters.mTxTotal++;
SentFrame(false); SentFrame(false);
break; break;
@@ -591,37 +593,65 @@ void Mac::SentFrame(bool aAcked)
Neighbor *neighbor; Neighbor *neighbor;
Sender *sender; 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) switch (mState)
{ {
case kStateActiveScan: case kStateActiveScan:
mCounters.mTxBeaconRequest++;
mAckTimer.Start(mScanDuration); mAckTimer.Start(mScanDuration);
break; break;
case kStateTransmitBeacon: case kStateTransmitBeacon:
mCounters.mTxBeacon++;
ScheduleNextTransmission(); ScheduleNextTransmission();
break; break;
case kStateTransmitData: case kStateTransmitData:
if (sendFrame.GetAckRequest() && !aAcked) if (mReceiveTimer.IsRunning())
{ {
otDumpDebgMac("NO ACK", sendFrame.GetHeader(), 16); mCounters.mTxDataPoll++;
}
if (mTransmitAttempts < kMaxFrameAttempts) else
{ {
mTransmitAttempts++; mCounters.mTxData++;
StartCsmaBackoff();
ExitNow();
}
sendFrame.GetDstAddr(destination);
if ((neighbor = mMle.GetNeighbor(destination)) != NULL)
{
neighbor->mState = Neighbor::kStateInvalid;
}
} }
mTransmitAttempts = 0;
sender = mSendHead; sender = mSendHead;
mSendHead = mSendHead->mNext; mSendHead = mSendHead->mNext;
@@ -750,8 +780,12 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
Neighbor *neighbor; Neighbor *neighbor;
Whitelist::Entry *entry; Whitelist::Entry *entry;
int8_t rssi; 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; aFrame->mSecurityValid = false;
@@ -769,7 +803,12 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
break; break;
case sizeof(ShortAddress): 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); srcaddr.mLength = sizeof(srcaddr.mExtAddress);
memcpy(&srcaddr.mExtAddress, &neighbor->mMacAddr, sizeof(srcaddr.mExtAddress)); memcpy(&srcaddr.mExtAddress, &neighbor->mMacAddr, sizeof(srcaddr.mExtAddress));
break; break;
@@ -778,13 +817,13 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
break; break;
default: default:
ExitNow(); ExitNow(error = kThreadError_InvalidSourceAddress);
} }
// Source Whitelist Processing // Source Whitelist Processing
if (srcaddr.mLength != 0 && mWhitelist.IsEnabled()) 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) if (mWhitelist.GetConstantRssi(*entry, rssi) == kThreadError_None)
{ {
@@ -804,26 +843,32 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
aFrame->GetDstPanId(panid); aFrame->GetDstPanId(panid);
VerifyOrExit((panid == kShortAddrBroadcast || panid == mPanId) && VerifyOrExit((panid == kShortAddrBroadcast || panid == mPanId) &&
((mRxOnWhenIdle && dstaddr.mShortAddress == kShortAddrBroadcast) || ((mRxOnWhenIdle && dstaddr.mShortAddress == kShortAddrBroadcast) ||
dstaddr.mShortAddress == mShortAddress), ;); dstaddr.mShortAddress == mShortAddress), error = kThreadError_DestinationAddressFiltered);
break; break;
case sizeof(ExtAddress): case sizeof(ExtAddress):
aFrame->GetDstPanId(panid); aFrame->GetDstPanId(panid);
VerifyOrExit(panid == mPanId && VerifyOrExit(panid == mPanId &&
memcmp(&dstaddr.mExtAddress, &mExtAddress, sizeof(dstaddr.mExtAddress)) == 0, ;); memcmp(&dstaddr.mExtAddress, &mExtAddress, sizeof(dstaddr.mExtAddress)) == 0,
error = kThreadError_DestinationAddressFiltered);
break; break;
} }
// Security Processing // Security Processing
SuccessOrExit(ProcessReceiveSecurity(*aFrame, srcaddr, neighbor)); SuccessOrExit(error = ProcessReceiveSecurity(*aFrame, srcaddr, neighbor));
switch (mState) switch (mState)
{ {
case kStateActiveScan: case kStateActiveScan:
if (aFrame->GetType() == Frame::kFcfFrameBeacon) if (aFrame->GetType() == Frame::kFcfFrameBeacon)
{ {
mCounters.mRxBeacon++;
mActiveScanHandler(mActiveScanContext, aFrame); mActiveScanHandler(mActiveScanContext, aFrame);
} }
else
{
mCounters.mRxOther++;
}
break; break;
@@ -833,9 +878,27 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
mReceiveTimer.Stop(); 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) for (Receiver *receiver = mReceiveHead; receiver; receiver = receiver->mNext)
@@ -847,6 +910,45 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
} }
exit: 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(); NextOperation();
} }
@@ -857,9 +959,12 @@ ThreadError Mac::HandleMacCommand(Frame &aFrame)
aFrame.GetCommandId(commandId); aFrame.GetCommandId(commandId);
if (commandId == Frame::kMacCmdBeaconRequest) switch (commandId)
{ {
case Frame::kMacCmdBeaconRequest:
mCounters.mRxBeaconRequest++;
otLogInfoMac("Received Beacon Request\n"); otLogInfoMac("Received Beacon Request\n");
mTransmitBeacon = true; mTransmitBeacon = true;
if (mState == kStateIdle) if (mState == kStateIdle)
@@ -870,6 +975,14 @@ ThreadError Mac::HandleMacCommand(Frame &aFrame)
} }
ExitNow(error = kThreadError_Drop); ExitNow(error = kThreadError_Drop);
case Frame::kMacCmdDataRequest:
mCounters.mRxDataPoll++;
break;
default:
mCounters.mRxOther++;
break;
} }
exit: exit:
@@ -902,5 +1015,10 @@ Whitelist &Mac::GetWhitelist(void)
return mWhitelist; return mWhitelist;
} }
otMacCounters &Mac::GetCounters(void)
{
return mCounters;
}
} // namespace Mac } // namespace Mac
} // namespace Thread } // namespace Thread
+10
View File
@@ -419,6 +419,14 @@ public:
*/ */
void SetPromiscuous(bool aPromiscuous); void SetPromiscuous(bool aPromiscuous);
/**
* This method returns the MAC counter.
*
* @returns A reference to the MAC counter.
*
*/
otMacCounters &GetCounters(void);
private: private:
void GenerateNonce(const ExtAddress &aAddress, uint32_t aFrameCounter, uint8_t aSecurityLevel, uint8_t *aNonce); void GenerateNonce(const ExtAddress &aAddress, uint32_t aFrameCounter, uint8_t aSecurityLevel, uint8_t *aNonce);
void NextOperation(void); void NextOperation(void);
@@ -484,6 +492,8 @@ private:
otLinkPcapCallback mPcapCallback; otLinkPcapCallback mPcapCallback;
Whitelist mWhitelist; Whitelist mWhitelist;
otMacCounters mCounters;
}; };
/** /**
+5
View File
@@ -515,6 +515,11 @@ exit:
return error; return error;
} }
const otMacCounters *otGetMacCounters(void)
{
return &sThreadNetif->GetMac().GetCounters();
}
bool otIsIp6AddressEqual(const otIp6Address *a, const otIp6Address *b) bool otIsIp6AddressEqual(const otIp6Address *a, const otIp6Address *b)
{ {
return *static_cast<const Ip6::Address *>(a) == *static_cast<const Ip6::Address *>(b); return *static_cast<const Ip6::Address *>(a) == *static_cast<const Ip6::Address *>(b);