diff --git a/src/cli/README.md b/src/cli/README.md index dbad40fef..7a89a53a2 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -1399,6 +1399,10 @@ Done Send an ICMPv6 Echo Request. +* size: The number of data bytes to be sent. +* count: The number of ICMPv6 Echo Requests to be sent. +* interval: The interval between two consecutive ICMPv6 Echo Requests in seconds. The value may have fractional form, for example `0.5`. + ```bash > ping fdde:ad00:beef:0:558:f56b:d688:799 16 bytes from fdde:ad00:beef:0:558:f56b:d688:799: icmp_seq=1 hlim=64 time=28ms diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 9c165e014..270c84f69 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -418,6 +418,52 @@ otError Interpreter::ParseUnsignedLong(char *argv, unsigned long &value) return (*endptr == '\0') ? OT_ERROR_NONE : OT_ERROR_PARSE; } +otError Interpreter::ParsePingInterval(const char *aString, uint32_t &aInterval) +{ + otError error = OT_ERROR_NONE; + const uint32_t msFactor = 1000; + uint32_t factor = msFactor; + + aInterval = 0; + + while (*aString) + { + if ('0' <= *aString && *aString <= '9') + { + // In the case of seconds, change the base of already calculated value. + if (factor == msFactor) + { + aInterval *= 10; + } + + aInterval += static_cast(*aString - '0') * factor; + + // In the case of milliseconds, change the multiplier factor. + if (factor != msFactor) + { + factor /= 10; + } + } + else if (*aString == '.') + { + // Accept only one dot character. + VerifyOrExit(factor == msFactor, error = OT_ERROR_PARSE); + + // Start analyzing hundreds of milliseconds. + factor /= 10; + } + else + { + ExitNow(error = OT_ERROR_PARSE); + } + + aString++; + } + +exit: + return error; +} + void Interpreter::ProcessHelp(int argc, char *argv[]) { OT_UNUSED_VARIABLE(argc); @@ -1926,9 +1972,10 @@ exit: void Interpreter::ProcessPing(int argc, char *argv[]) { - otError error = OT_ERROR_NONE; - uint8_t index = 1; - long value; + otError error = OT_ERROR_NONE; + uint8_t index = 1; + long value; + uint32_t interval; VerifyOrExit(argc > 0, error = OT_ERROR_INVALID_ARGS); @@ -1957,21 +2004,22 @@ void Interpreter::ProcessPing(int argc, char *argv[]) while (index < argc) { - SuccessOrExit(error = ParseLong(argv[index], value)); - switch (index) { case 1: + SuccessOrExit(error = ParseLong(argv[index], value)); mLength = static_cast(value); break; case 2: + SuccessOrExit(error = ParseLong(argv[index], value)); mCount = static_cast(value); break; case 3: - VerifyOrExit(0 < value && value <= Timer::kMaxDt / 1000, error = OT_ERROR_INVALID_ARGS); - mInterval = static_cast(value) * 1000; + SuccessOrExit(error = ParsePingInterval(argv[index], interval)); + VerifyOrExit(0 < interval && interval <= Timer::kMaxDt, error = OT_ERROR_INVALID_ARGS); + mInterval = interval; break; default: diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index b7bb6e900..a7e6aa49c 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -188,10 +188,11 @@ private: kDefaultJoinerTimeout = 120, ///< Default timeout for Joiners, in seconds. }; - void ProcessHelp(int argc, char *argv[]); - void ProcessAutoStart(int argc, char *argv[]); - void ProcessBufferInfo(int argc, char *argv[]); - void ProcessChannel(int argc, char *argv[]); + otError ParsePingInterval(const char *aString, uint32_t &aInterval); + void ProcessHelp(int argc, char *argv[]); + void ProcessAutoStart(int argc, char *argv[]); + void ProcessBufferInfo(int argc, char *argv[]); + void ProcessChannel(int argc, char *argv[]); #if OPENTHREAD_FTD void ProcessChild(int argc, char *argv[]); void ProcessChildMax(int argc, char *argv[]);