[posix] add rcp capability diag command to check the Spinel interface speed (#10443)

This commit is contained in:
Zhanglong Xia
2024-07-01 19:16:10 -07:00
committed by GitHub
parent a448bce915
commit 2d3df2acee
5 changed files with 122 additions and 0 deletions
+6
View File
@@ -1771,6 +1771,12 @@ void RadioSpinel::SetDiagOutputCallback(otPlatDiagOutputCallback aCallback, void
mOutputContext = aContext;
}
void RadioSpinel::GetDiagOutputCallback(otPlatDiagOutputCallback &aCallback, void *&aContext)
{
aCallback = mOutputCallback;
aContext = mOutputContext;
}
otError RadioSpinel::PlatDiagProcess(const char *aString)
{
return Set(SPINEL_PROP_NEST_STREAM_MFG, SPINEL_DATATYPE_UTF8_S, aString);
+9
View File
@@ -695,6 +695,15 @@ public:
*
*/
void SetDiagOutputCallback(otPlatDiagOutputCallback aCallback, void *aContext);
/**
* Gets the diag output callback.
*
* @param[out] aCallback A reference to a function that is called on outputting diag messages.
* @param[out] aContext A reference to the user context.
*
*/
void GetDiagOutputCallback(otPlatDiagOutputCallback &aCallback, void *&aContext);
#endif
/**
@@ -8,6 +8,7 @@ This module provides diag commands for checking RCP capabilities.
- [capflags](#capflags)
- [spinel](#spinel)
- [spinelspeed](#spinelspeed)
- [srcmatchtable](#srcmatchtable)
## Command Details
@@ -114,6 +115,16 @@ PROP_VALUE_SET RADIO_COEX_ENABLE -------------------------- OK
Done
```
### spinelspeed
Check the speed of Spinel interface.
```bash
> diag rcpcaps spinelspeed
SpinelSpeed ----------------------------------------------- 34414843 bps
Done
```
### srcmatchtable
Check the source match table size supported by the RCP.
+87
View File
@@ -28,6 +28,8 @@
#include "rcp_caps_diag.hpp"
#include "lib/utils/math.hpp"
#if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
namespace ot {
namespace Posix {
@@ -465,6 +467,10 @@ otError RcpCapsDiag::DiagProcess(char *aArgs[], uint8_t aArgsLength)
{
ProcessSpinel();
}
else if (strcmp(aArgs[1], "spinelspeed") == 0)
{
ProcessSpinelSpeed();
}
else
{
error = OT_ERROR_INVALID_COMMAND;
@@ -680,6 +686,87 @@ exit:
OutputFormat("ExtendedSrcMatchTableSize", num);
}
void RcpCapsDiag::HandleDiagOutput(const char *aFormat, va_list aArguments, void *aContext)
{
static_cast<RcpCapsDiag *>(aContext)->HandleDiagOutput(aFormat, aArguments);
}
void RcpCapsDiag::HandleDiagOutput(const char *aFormat, va_list aArguments)
{
int rval;
VerifyOrExit(mDiagOutput != nullptr && mDiagOutputLength != 0);
rval = vsnprintf(mDiagOutput, mDiagOutputLength, aFormat, aArguments);
VerifyOrExit(rval >= 0);
rval = (rval > mDiagOutputLength) ? mDiagOutputLength : rval;
mDiagOutput += rval;
mDiagOutputLength -= rval;
exit:
return;
}
void RcpCapsDiag::ProcessSpinelSpeed(void)
{
static constexpr uint32_t kUsPerSec = 1000000;
static constexpr uint8_t kBitsPerByte = 8;
static constexpr uint8_t kSpinelHeaderSize = 4;
static constexpr uint8_t kZeroTerminatorSize = 1;
static constexpr char kEchoCmd[] = "echo ";
static constexpr uint8_t kEchoPayloadLength = 200;
static constexpr uint8_t kNumTests = 100;
otError error = OT_ERROR_NONE;
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE] = {0};
char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
uint16_t echoPayloadLength;
uint64_t startTimestamp;
uint64_t endTimestamp;
uint64_t sumTime = 0;
uint64_t sumLength = 0;
uint32_t speed;
otPlatDiagOutputCallback callback;
void *context;
mRadioSpinel.GetDiagOutputCallback(callback, context);
mRadioSpinel.SetDiagOutputCallback(HandleDiagOutput, this);
strncpy(cmd, kEchoCmd, sizeof(cmd) - 1);
echoPayloadLength = static_cast<uint16_t>(sizeof(cmd) - strlen(cmd) - 1);
echoPayloadLength = Lib::Utils::Min<uint16_t>(kEchoPayloadLength, echoPayloadLength);
memset(cmd + strlen(cmd), '1', echoPayloadLength);
for (uint16_t i = 0; i < kNumTests; i++)
{
output[0] = '\0';
mDiagOutput = output;
mDiagOutputLength = sizeof(output);
startTimestamp = otPlatTimeGet();
SuccessOrExit(error = mRadioSpinel.PlatDiagProcess(cmd));
endTimestamp = otPlatTimeGet();
sumTime += endTimestamp - startTimestamp;
sumLength += kSpinelHeaderSize + strlen(cmd) + kZeroTerminatorSize + kSpinelHeaderSize + strlen(output) +
kZeroTerminatorSize;
}
mRadioSpinel.SetDiagOutputCallback(callback, context);
exit:
if (error == OT_ERROR_NONE)
{
speed = static_cast<uint32_t>((sumLength * kBitsPerByte * kUsPerSec) / sumTime);
snprintf(output, sizeof(output), "%lu bps", ToUlong(speed));
OutputFormat("SpinelSpeed", output);
}
else
{
Output("Failed to test the Spinel speed: %s", otThreadErrorToString(error));
}
}
void RcpCapsDiag::OutputFormat(const char *aName, const char *aValue)
{
static constexpr uint8_t kMaxNameLength = 56;
+9
View File
@@ -62,6 +62,8 @@ public:
: mRadioSpinel(aRadioSpinel)
, mOutputCallback(nullptr)
, mOutputContext(nullptr)
, mDiagOutput(nullptr)
, mDiagOutputLength(0)
{
}
@@ -111,6 +113,7 @@ private:
static constexpr uint16_t kMaxNumChildren = 512;
void ProcessSpinel(void);
void ProcessSpinelSpeed(void);
void ProcessCapabilityFlags(void);
void ProcessSrcMatchTable(void);
void TestSpinelCommands(Category aCategory);
@@ -125,6 +128,10 @@ private:
bool IsSpinelCapabilitySupported(const uint8_t *aCapsData, spinel_size_t aCapsLength, uint32_t aCapability);
void OutputExtendedSrcMatchTableSize(void);
void OutputShortSrcMatchTableSize(void);
static void HandleDiagOutput(const char *aFormat, va_list aArguments, void *aContext);
void HandleDiagOutput(const char *aFormat, va_list aArguments);
void OutputFormat(const char *aName, const char *aValue);
void OutputFormat(const char *aName, uint32_t aValue);
void OutputResult(const SpinelEntry &aEntry, otError error);
@@ -139,6 +146,8 @@ private:
Spinel::RadioSpinel &mRadioSpinel;
otPlatDiagOutputCallback mOutputCallback;
void *mOutputContext;
char *mDiagOutput;
uint16_t mDiagOutputLength;
};
} // namespace Posix