mirror of
https://github.com/espressif/openthread.git
synced 2026-09-01 14:59:54 +00:00
[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:
committed by
Jonathan Hui
parent
5e6e262dfb
commit
c2d22744c0
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user