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 15:32:51 +08: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,
/**
* 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;
/**
* @}
*
+7
View File
@@ -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);
/**
* @}
*
+42
View File
@@ -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();
+1
View File
@@ -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
View File
@@ -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
+10
View File
@@ -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;
};
/**
+5
View File
@@ -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);