[link-quality] adding SuccessRateTracker and tracking CCA failure rate (#2493)

This commit adds a new class `SuccessRateTracker` which can be used to
tracker success/failure rate of an operation. It uses an exponentially
moving average IIR filter to maintain the rate using  a `uint16_t` as
its storage. Unit test `test_link_quality` is updated to include a new
test case ``ot::TestSuccessRateTracker()` verifying the behavior of
the new class.

This commit uses the new class to track the CCA failure rate (over all
frame transmissions) at MAC layer.
This commit is contained in:
Abtin Keshavarzian
2018-01-22 16:56:18 +00:00
committed by Jonathan Hui
parent 5e6e262dfb
commit c2d22744c0
8 changed files with 254 additions and 7 deletions
+111 -2
View File
@@ -287,7 +287,7 @@ void TestRssAveraging(void)
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adding two alteraing values many times:
// Adding two alternating values many times:
printf("- - - - - - - - - - - - - - - - - -\n");
@@ -394,6 +394,114 @@ void TestLinkQualityCalculations(void)
TestLinkQualityData(rssData4);
}
void TestSuccessRateTracker(void)
{
SuccessRateTracker rateTracker;
uint16_t sampleCount;
const uint16_t kMaxSamples = 5000;
const uint16_t kMaxRate = SuccessRateTracker::kMaxRateValue;
const double kMaxError = 1.0; // Max permitted error in percentage
const uint16_t kWeightLimit[] = { 64, 128, 256, 300, 512, 810, 900 };
printf("\nTesting SuccessRateTracker\n");
VerifyOrQuit(rateTracker.GetSuccessRate() == kMaxRate, "SuccessRateTracker: Initial value incorrect");
VerifyOrQuit(rateTracker.GetFailureRate() == 0, "SuccessRateTracker: Initial value incorrect");
// Adding all success
for (sampleCount = 1; sampleCount < kMaxSamples; sampleCount++)
{
rateTracker.AddSample(true, sampleCount);
VerifyOrQuit(rateTracker.GetSuccessRate() == kMaxRate, "SuccessRateTracker: incorrect rate all success case");
VerifyOrQuit(rateTracker.GetFailureRate() == 0, "SuccessRateTracker: incorrect rate in all success case");
}
rateTracker.Reset();
VerifyOrQuit(rateTracker.GetSuccessRate() == kMaxRate, "SuccessRateTracker: Rate incorrect after reset");
VerifyOrQuit(rateTracker.GetFailureRate() == 0, "SuccessRateTracker: Rate incorrect after reset");
// Adding all failures
for (sampleCount = 1; sampleCount < kMaxRate; sampleCount++)
{
rateTracker.AddSample(false, sampleCount);
VerifyOrQuit(rateTracker.GetSuccessRate() == 0, "SuccessRateTracker: rate incorrect all failure case");
VerifyOrQuit(rateTracker.GetFailureRate() == kMaxRate, "SuccessRateTracker: rate incorrect in all failure case");
}
// Adding success/failure at different rates and checking the RateTracker rate for every sample
for (uint16_t testRound = 0; testRound < sizeof(kWeightLimit) / sizeof(kWeightLimit[0]) * 2; testRound++)
{
uint16_t weightLimit;
bool reverseLogic;
double maxDiff = 0;
// Reverse the logic (add success instead of failure) on even test rounds
reverseLogic = ((testRound % 2) == 0);
// Select a different weight limit based on the current test round
weightLimit = kWeightLimit[testRound / 2];
printf("TestRound %02d, weightLimit %3d, reverseLogic %d ", testRound, weightLimit, reverseLogic);
for (uint16_t period = 1; period < 101; period++)
{
uint16_t failureCount = 0;
rateTracker.Reset();
for (sampleCount = 1; sampleCount < kMaxSamples; sampleCount++)
{
double expectedRate;
double failureRate;
double diff;
bool isSuccess = ((sampleCount % period) == 0);
uint16_t weight;
if (reverseLogic)
{
isSuccess = !isSuccess;
}
weight = sampleCount;
if (weight > weightLimit)
{
weight = weightLimit;
}
rateTracker.AddSample(isSuccess, weight);
if (!isSuccess)
{
failureCount++;
}
// Calculate the failure rate from rateTracker and expected rate.
failureRate = static_cast<double>(rateTracker.GetFailureRate()) * 100.0 / kMaxRate; // in percent
expectedRate = static_cast<double>(failureCount) * 100.0 / sampleCount; // in percent
diff = failureRate - expectedRate;
diff = ABS(diff);
VerifyOrQuit(diff <= kMaxError, "SuccessRateTracker: rate does not match expected value");
if (diff > maxDiff)
{
maxDiff = diff;
}
}
}
printf(" MaxDiff = %.3f%%-> PASS\n", maxDiff);
}
}
} // namespace ot
#ifdef ENABLE_TEST_MAIN
@@ -401,7 +509,8 @@ int main(void)
{
ot::TestRssAveraging();
ot::TestLinkQualityCalculations();
printf("All tests passed\n");
ot::TestSuccessRateTracker();
printf("\nAll tests passed\n");
return 0;
}
#endif