mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
[cli] separate ping sender as a module (#9756)
This commit is contained in:
@@ -57,6 +57,8 @@ openthread_cli_sources = [
|
||||
"cli_network_data.hpp",
|
||||
"cli_output.cpp",
|
||||
"cli_output.hpp",
|
||||
"cli_ping.cpp",
|
||||
"cli_ping.hpp",
|
||||
"cli_srp_client.cpp",
|
||||
"cli_srp_client.hpp",
|
||||
"cli_srp_server.cpp",
|
||||
|
||||
@@ -46,6 +46,7 @@ set(COMMON_SOURCES
|
||||
cli_mac_filter.cpp
|
||||
cli_network_data.cpp
|
||||
cli_output.cpp
|
||||
cli_ping.cpp
|
||||
cli_srp_client.cpp
|
||||
cli_srp_server.cpp
|
||||
cli_tcat.cpp
|
||||
|
||||
+4
-202
@@ -152,6 +152,9 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
, mTcat(aInstance, *this)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
, mPing(aInstance, *this)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
|
||||
, mLocateInProgress(false)
|
||||
#endif
|
||||
@@ -447,57 +450,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
|
||||
otError Interpreter::ParsePingInterval(const Arg &aArg, uint32_t &aInterval)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
const char *string = aArg.GetCString();
|
||||
const uint32_t msFactor = 1000;
|
||||
uint32_t factor = msFactor;
|
||||
|
||||
aInterval = 0;
|
||||
|
||||
while (*string)
|
||||
{
|
||||
if ('0' <= *string && *string <= '9')
|
||||
{
|
||||
// In the case of seconds, change the base of already calculated value.
|
||||
if (factor == msFactor)
|
||||
{
|
||||
aInterval *= 10;
|
||||
}
|
||||
|
||||
aInterval += static_cast<uint32_t>(*string - '0') * factor;
|
||||
|
||||
// In the case of milliseconds, change the multiplier factor.
|
||||
if (factor != msFactor)
|
||||
{
|
||||
factor /= 10;
|
||||
}
|
||||
}
|
||||
else if (*string == '.')
|
||||
{
|
||||
// Accept only one dot character.
|
||||
VerifyOrExit(factor == msFactor, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
// Start analyzing hundreds of milliseconds.
|
||||
factor /= 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
|
||||
string++;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
|
||||
otError Interpreter::ParsePreference(const Arg &aArg, otRoutePreference &aPreference)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
@@ -5550,55 +5502,6 @@ exit:
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
|
||||
void Interpreter::HandlePingReply(const otPingSenderReply *aReply, void *aContext)
|
||||
{
|
||||
static_cast<Interpreter *>(aContext)->HandlePingReply(aReply);
|
||||
}
|
||||
|
||||
void Interpreter::HandlePingReply(const otPingSenderReply *aReply)
|
||||
{
|
||||
OutputFormat("%u bytes from ", static_cast<uint16_t>(aReply->mSize + sizeof(otIcmp6Header)));
|
||||
OutputIp6Address(aReply->mSenderAddress);
|
||||
OutputLine(": icmp_seq=%u hlim=%u time=%ums", aReply->mSequenceNumber, aReply->mHopLimit, aReply->mRoundTripTime);
|
||||
}
|
||||
|
||||
void Interpreter::HandlePingStatistics(const otPingSenderStatistics *aStatistics, void *aContext)
|
||||
{
|
||||
static_cast<Interpreter *>(aContext)->HandlePingStatistics(aStatistics);
|
||||
}
|
||||
|
||||
void Interpreter::HandlePingStatistics(const otPingSenderStatistics *aStatistics)
|
||||
{
|
||||
OutputFormat("%u packets transmitted, %u packets received.", aStatistics->mSentCount, aStatistics->mReceivedCount);
|
||||
|
||||
if ((aStatistics->mSentCount != 0) && !aStatistics->mIsMulticast &&
|
||||
aStatistics->mReceivedCount <= aStatistics->mSentCount)
|
||||
{
|
||||
uint32_t packetLossRate =
|
||||
1000 * (aStatistics->mSentCount - aStatistics->mReceivedCount) / aStatistics->mSentCount;
|
||||
|
||||
OutputFormat(" Packet loss = %lu.%u%%.", ToUlong(packetLossRate / 10),
|
||||
static_cast<uint16_t>(packetLossRate % 10));
|
||||
}
|
||||
|
||||
if (aStatistics->mReceivedCount != 0)
|
||||
{
|
||||
uint32_t avgRoundTripTime = 1000 * aStatistics->mTotalRoundTripTime / aStatistics->mReceivedCount;
|
||||
|
||||
OutputFormat(" Round-trip min/avg/max = %u/%u.%u/%u ms.", aStatistics->mMinRoundTripTime,
|
||||
static_cast<uint16_t>(avgRoundTripTime / 1000), static_cast<uint16_t>(avgRoundTripTime % 1000),
|
||||
aStatistics->mMaxRoundTripTime);
|
||||
}
|
||||
|
||||
OutputNewLine();
|
||||
|
||||
if (!mPingIsAsync)
|
||||
{
|
||||
OutputResult(OT_ERROR_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @cli ping
|
||||
* @code
|
||||
@@ -5634,108 +5537,7 @@ void Interpreter::HandlePingStatistics(const otPingSenderStatistics *aStatistics
|
||||
* Note: The command will return InvalidState when the preferred NAT64 prefix is unavailable.
|
||||
* @sa otPingSenderPing
|
||||
*/
|
||||
template <> otError Interpreter::Process<Cmd("ping")>(Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otPingSenderConfig config;
|
||||
bool async = false;
|
||||
bool nat64SynthesizedAddress;
|
||||
|
||||
/**
|
||||
* @cli ping stop
|
||||
* @code
|
||||
* ping stop
|
||||
* Done
|
||||
* @endcode
|
||||
* @par
|
||||
* Stop sending ICMPv6 Echo Requests.
|
||||
* @sa otPingSenderStop
|
||||
*/
|
||||
if (aArgs[0] == "stop")
|
||||
{
|
||||
otPingSenderStop(GetInstancePtr());
|
||||
ExitNow();
|
||||
}
|
||||
else if (aArgs[0] == "async")
|
||||
{
|
||||
async = true;
|
||||
aArgs++;
|
||||
}
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
|
||||
if (aArgs[0] == "-I")
|
||||
{
|
||||
SuccessOrExit(error = aArgs[1].ParseAsIp6Address(config.mSource));
|
||||
|
||||
#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||
VerifyOrExit(otIp6HasUnicastAddress(GetInstancePtr(), &config.mSource), error = OT_ERROR_INVALID_ARGS);
|
||||
#endif
|
||||
aArgs += 2;
|
||||
}
|
||||
|
||||
if (aArgs[0] == "-m")
|
||||
{
|
||||
config.mMulticastLoop = true;
|
||||
aArgs++;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = ParseToIp6Address(GetInstancePtr(), aArgs[0], config.mDestination, nat64SynthesizedAddress));
|
||||
if (nat64SynthesizedAddress)
|
||||
{
|
||||
OutputFormat("Pinging synthesized IPv6 address: ");
|
||||
OutputIp6AddressLine(config.mDestination);
|
||||
}
|
||||
|
||||
if (!aArgs[1].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aArgs[1].ParseAsUint16(config.mSize));
|
||||
}
|
||||
|
||||
if (!aArgs[2].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aArgs[2].ParseAsUint16(config.mCount));
|
||||
}
|
||||
|
||||
if (!aArgs[3].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = ParsePingInterval(aArgs[3], config.mInterval));
|
||||
}
|
||||
|
||||
if (!aArgs[4].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aArgs[4].ParseAsUint8(config.mHopLimit));
|
||||
config.mAllowZeroHopLimit = (config.mHopLimit == 0);
|
||||
}
|
||||
|
||||
if (!aArgs[5].IsEmpty())
|
||||
{
|
||||
uint32_t timeout;
|
||||
|
||||
SuccessOrExit(error = ParsePingInterval(aArgs[5], timeout));
|
||||
VerifyOrExit(timeout <= NumericLimits<uint16_t>::kMax, error = OT_ERROR_INVALID_ARGS);
|
||||
config.mTimeout = static_cast<uint16_t>(timeout);
|
||||
}
|
||||
|
||||
VerifyOrExit(aArgs[6].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
config.mReplyCallback = Interpreter::HandlePingReply;
|
||||
config.mStatisticsCallback = Interpreter::HandlePingStatistics;
|
||||
config.mCallbackContext = this;
|
||||
|
||||
SuccessOrExit(error = otPingSenderPing(GetInstancePtr(), &config));
|
||||
|
||||
mPingIsAsync = async;
|
||||
|
||||
if (!async)
|
||||
{
|
||||
error = OT_ERROR_PENDING;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
template <> otError Interpreter::Process<Cmd("ping")>(Arg aArgs[]) { return mPing.Process(aArgs); }
|
||||
#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
|
||||
/**
|
||||
|
||||
+5
-14
@@ -69,6 +69,7 @@
|
||||
#include "cli/cli_mac_filter.hpp"
|
||||
#include "cli/cli_network_data.hpp"
|
||||
#include "cli/cli_output.hpp"
|
||||
#include "cli/cli_ping.hpp"
|
||||
#include "cli/cli_srp_client.hpp"
|
||||
#include "cli/cli_srp_server.hpp"
|
||||
#include "cli/cli_tcat.hpp"
|
||||
@@ -117,6 +118,7 @@ class Interpreter : public OutputImplementer, public Output
|
||||
friend class Joiner;
|
||||
friend class LinkMetrics;
|
||||
friend class NetworkData;
|
||||
friend class PingSender;
|
||||
friend class SrpClient;
|
||||
friend class SrpServer;
|
||||
#endif
|
||||
@@ -382,9 +384,6 @@ private:
|
||||
void OutputPrompt(void);
|
||||
void OutputResult(otError aError);
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
otError ParsePingInterval(const Arg &aArg, uint32_t &aInterval);
|
||||
#endif
|
||||
static otError ParseJoinerDiscerner(Arg &aArg, otJoinerDiscerner &aDiscerner);
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
static otError ParsePrefix(Arg aArgs[], otBorderRouterConfig &aConfig);
|
||||
@@ -458,10 +457,6 @@ private:
|
||||
void OutputMultiRadioInfo(const otMultiRadioNeighborInfo &aMultiRadioInfo);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
static void HandlePingReply(const otPingSenderReply *aReply, void *aContext);
|
||||
static void HandlePingStatistics(const otPingSenderStatistics *aStatistics, void *aContext);
|
||||
#endif
|
||||
static void HandleActiveScanResult(otActiveScanResult *aResult, void *aContext);
|
||||
static void HandleEnergyScanResult(otEnergyScanResult *aResult, void *aContext);
|
||||
static void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx, void *aContext);
|
||||
@@ -497,10 +492,6 @@ private:
|
||||
static void HandleSntpResponse(void *aContext, uint64_t aTime, otError aResult);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
void HandlePingReply(const otPingSenderReply *aReply);
|
||||
void HandlePingStatistics(const otPingSenderStatistics *aStatistics);
|
||||
#endif
|
||||
void HandleActiveScanResult(otActiveScanResult *aResult);
|
||||
void HandleEnergyScanResult(otEnergyScanResult *aResult);
|
||||
void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx);
|
||||
@@ -602,11 +593,11 @@ private:
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
Tcat mTcat;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
PingSender mPing;
|
||||
#endif
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
bool mPingIsAsync : 1;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
|
||||
bool mLocateInProgress : 1;
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) 2024, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the CLI interpreter for Ping Sender function.
|
||||
*/
|
||||
|
||||
#include "cli_ping.hpp"
|
||||
|
||||
#include <openthread/ping_sender.h>
|
||||
|
||||
#include "cli/cli.hpp"
|
||||
#include "cli/cli_output.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
|
||||
namespace ot {
|
||||
namespace Cli {
|
||||
|
||||
PingSender::PingSender(otInstance *aInstance, OutputImplementer &aOutputImplementer)
|
||||
: Output(aInstance, aOutputImplementer)
|
||||
, mPingIsAsync(false)
|
||||
{
|
||||
}
|
||||
|
||||
otError PingSender::Process(Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otPingSenderConfig config;
|
||||
bool async = false;
|
||||
bool nat64SynthesizedAddress;
|
||||
|
||||
/**
|
||||
* @cli ping stop
|
||||
* @code
|
||||
* ping stop
|
||||
* Done
|
||||
* @endcode
|
||||
* @par
|
||||
* Stop sending ICMPv6 Echo Requests.
|
||||
* @sa otPingSenderStop
|
||||
*/
|
||||
if (aArgs[0] == "stop")
|
||||
{
|
||||
otPingSenderStop(GetInstancePtr());
|
||||
ExitNow();
|
||||
}
|
||||
else if (aArgs[0] == "async")
|
||||
{
|
||||
async = true;
|
||||
aArgs++;
|
||||
}
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
|
||||
if (aArgs[0] == "-I")
|
||||
{
|
||||
SuccessOrExit(error = aArgs[1].ParseAsIp6Address(config.mSource));
|
||||
|
||||
#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||
VerifyOrExit(otIp6HasUnicastAddress(GetInstancePtr(), &config.mSource), error = OT_ERROR_INVALID_ARGS);
|
||||
#endif
|
||||
aArgs += 2;
|
||||
}
|
||||
|
||||
if (aArgs[0] == "-m")
|
||||
{
|
||||
config.mMulticastLoop = true;
|
||||
aArgs++;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = Interpreter::GetInterpreter().ParseToIp6Address(
|
||||
GetInstancePtr(), aArgs[0], config.mDestination, nat64SynthesizedAddress));
|
||||
if (nat64SynthesizedAddress)
|
||||
{
|
||||
OutputFormat("Pinging synthesized IPv6 address: ");
|
||||
OutputIp6AddressLine(config.mDestination);
|
||||
}
|
||||
|
||||
if (!aArgs[1].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aArgs[1].ParseAsUint16(config.mSize));
|
||||
}
|
||||
|
||||
if (!aArgs[2].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aArgs[2].ParseAsUint16(config.mCount));
|
||||
}
|
||||
|
||||
if (!aArgs[3].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = ParsePingInterval(aArgs[3], config.mInterval));
|
||||
}
|
||||
|
||||
if (!aArgs[4].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aArgs[4].ParseAsUint8(config.mHopLimit));
|
||||
config.mAllowZeroHopLimit = (config.mHopLimit == 0);
|
||||
}
|
||||
|
||||
if (!aArgs[5].IsEmpty())
|
||||
{
|
||||
uint32_t timeout;
|
||||
|
||||
SuccessOrExit(error = ParsePingInterval(aArgs[5], timeout));
|
||||
VerifyOrExit(timeout <= NumericLimits<uint16_t>::kMax, error = OT_ERROR_INVALID_ARGS);
|
||||
config.mTimeout = static_cast<uint16_t>(timeout);
|
||||
}
|
||||
|
||||
VerifyOrExit(aArgs[6].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
config.mReplyCallback = PingSender::HandlePingReply;
|
||||
config.mStatisticsCallback = PingSender::HandlePingStatistics;
|
||||
config.mCallbackContext = this;
|
||||
|
||||
SuccessOrExit(error = otPingSenderPing(GetInstancePtr(), &config));
|
||||
|
||||
mPingIsAsync = async;
|
||||
|
||||
if (!async)
|
||||
{
|
||||
error = OT_ERROR_PENDING;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError PingSender::ParsePingInterval(const Arg &aArg, uint32_t &aInterval)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
const char *string = aArg.GetCString();
|
||||
const uint32_t msFactor = 1000;
|
||||
uint32_t factor = msFactor;
|
||||
|
||||
aInterval = 0;
|
||||
|
||||
while (*string)
|
||||
{
|
||||
if ('0' <= *string && *string <= '9')
|
||||
{
|
||||
// In the case of seconds, change the base of already calculated value.
|
||||
if (factor == msFactor)
|
||||
{
|
||||
aInterval *= 10;
|
||||
}
|
||||
|
||||
aInterval += static_cast<uint32_t>(*string - '0') * factor;
|
||||
|
||||
// In the case of milliseconds, change the multiplier factor.
|
||||
if (factor != msFactor)
|
||||
{
|
||||
factor /= 10;
|
||||
}
|
||||
}
|
||||
else if (*string == '.')
|
||||
{
|
||||
// Accept only one dot character.
|
||||
VerifyOrExit(factor == msFactor, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
// Start analyzing hundreds of milliseconds.
|
||||
factor /= 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
|
||||
string++;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void PingSender::HandlePingReply(const otPingSenderReply *aReply, void *aContext)
|
||||
{
|
||||
static_cast<PingSender *>(aContext)->HandlePingReply(aReply);
|
||||
}
|
||||
|
||||
void PingSender::HandlePingReply(const otPingSenderReply *aReply)
|
||||
{
|
||||
OutputFormat("%u bytes from ", static_cast<uint16_t>(aReply->mSize + sizeof(otIcmp6Header)));
|
||||
OutputIp6Address(aReply->mSenderAddress);
|
||||
OutputLine(": icmp_seq=%u hlim=%u time=%ums", aReply->mSequenceNumber, aReply->mHopLimit, aReply->mRoundTripTime);
|
||||
}
|
||||
|
||||
void PingSender::HandlePingStatistics(const otPingSenderStatistics *aStatistics, void *aContext)
|
||||
{
|
||||
static_cast<PingSender *>(aContext)->HandlePingStatistics(aStatistics);
|
||||
}
|
||||
|
||||
void PingSender::HandlePingStatistics(const otPingSenderStatistics *aStatistics)
|
||||
{
|
||||
OutputFormat("%u packets transmitted, %u packets received.", aStatistics->mSentCount, aStatistics->mReceivedCount);
|
||||
|
||||
if ((aStatistics->mSentCount != 0) && !aStatistics->mIsMulticast &&
|
||||
aStatistics->mReceivedCount <= aStatistics->mSentCount)
|
||||
{
|
||||
uint32_t packetLossRate =
|
||||
1000 * (aStatistics->mSentCount - aStatistics->mReceivedCount) / aStatistics->mSentCount;
|
||||
|
||||
OutputFormat(" Packet loss = %lu.%u%%.", ToUlong(packetLossRate / 10),
|
||||
static_cast<uint16_t>(packetLossRate % 10));
|
||||
}
|
||||
|
||||
if (aStatistics->mReceivedCount != 0)
|
||||
{
|
||||
uint32_t avgRoundTripTime = 1000 * aStatistics->mTotalRoundTripTime / aStatistics->mReceivedCount;
|
||||
|
||||
OutputFormat(" Round-trip min/avg/max = %u/%u.%u/%u ms.", aStatistics->mMinRoundTripTime,
|
||||
static_cast<uint16_t>(avgRoundTripTime / 1000), static_cast<uint16_t>(avgRoundTripTime % 1000),
|
||||
aStatistics->mMaxRoundTripTime);
|
||||
}
|
||||
|
||||
OutputNewLine();
|
||||
|
||||
if (!mPingIsAsync)
|
||||
{
|
||||
OutputResult(OT_ERROR_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void PingSender::OutputResult(otError aError) { Interpreter::GetInterpreter().OutputResult(aError); }
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2024, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file contains definitions for the CLI interpreter for Ping Sneder function.
|
||||
*/
|
||||
|
||||
#ifndef CLI_PING_SENDER_HPP_
|
||||
#define CLI_PING_SENDER_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/ping_sender.h>
|
||||
|
||||
#include "cli/cli_output.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
|
||||
namespace ot {
|
||||
namespace Cli {
|
||||
|
||||
/**
|
||||
* Implements the Ping Sender CLI interpreter.
|
||||
*
|
||||
*/
|
||||
|
||||
class PingSender : private Output
|
||||
{
|
||||
public:
|
||||
typedef Utils::CmdLineParser::Arg Arg;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param[in] aInstance The OpenThread Instance.
|
||||
* @param[in] aOutputImplementer An `OutputImplementer`.
|
||||
*
|
||||
*/
|
||||
PingSender(otInstance *aInstance, OutputImplementer &aOutputImplementer);
|
||||
|
||||
/**
|
||||
* Processes a CLI sub-command.
|
||||
*
|
||||
* @param[in] aArgs An array of command line arguments.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully executed the CLI command.
|
||||
* @retval OT_ERROR_PENDING The CLI command was successfully started but final result is pending.
|
||||
* @retval OT_ERROR_INVALID_COMMAND Invalid or unknown CLI command.
|
||||
* @retval OT_ERROR_INVALID_ARGS Invalid arguments.
|
||||
* @retval ... Error during execution of the CLI command.
|
||||
*
|
||||
*/
|
||||
otError Process(Arg aArgs[]);
|
||||
|
||||
private:
|
||||
otError ParsePingInterval(const Arg &aArg, uint32_t &aInterval);
|
||||
|
||||
static void HandlePingReply(const otPingSenderReply *aReply, void *aContext);
|
||||
void HandlePingReply(const otPingSenderReply *aReply);
|
||||
static void HandlePingStatistics(const otPingSenderStatistics *aStatistics, void *aContext);
|
||||
void HandlePingStatistics(const otPingSenderStatistics *aStatistics);
|
||||
|
||||
void OutputResult(otError aError);
|
||||
|
||||
bool mPingIsAsync : 1;
|
||||
};
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
|
||||
#endif // CLI_PING_SENDER_HPP_
|
||||
Reference in New Issue
Block a user