mirror of
https://github.com/espressif/openthread.git
synced 2026-07-19 10:34:07 +00:00
[cli] use ICMPv6 Echo Request ID to match Responses (#4534)
This commit updates/enhances the CLI `ping` command. It adds the
feature to track and match the ICMPv6 echo requests and responses
using an identifier. Each `ping` command will use a new value as the
identifier. A received ICMPv6 echo response not matching the current
identifier is ignored. This commit also makes the following (smaller)
changes:
- renames the ping related member variables as `mPing{Name}`,
- defines constants for default ping parameters,
- changes `ping` to use public OT APIs/definition (instead of core
methods).
This commit is contained in:
committed by
Jonathan Hui
parent
aa78b2688e
commit
253e99ba17
+63
-55
@@ -225,9 +225,12 @@ Interpreter::Interpreter(Instance *aInstance)
|
||||
: mUserCommands(NULL)
|
||||
, mUserCommandsLength(0)
|
||||
, mServer(NULL)
|
||||
, mLength(8)
|
||||
, mCount(1)
|
||||
, mInterval(1000)
|
||||
, mPingLength(kDefaultPingLength)
|
||||
, mPingCount(kDefaultPingCount)
|
||||
, mPingInterval(kDefaultPingInterval)
|
||||
, mPingHopLimit(0)
|
||||
, mPingAllowZeroHopLimit(false)
|
||||
, mPingIdentifier(0)
|
||||
, mPingTimer(*aInstance, &Interpreter::HandlePingTimer, this)
|
||||
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
|
||||
, mResolvingInProgress(0)
|
||||
@@ -1983,27 +1986,26 @@ void Interpreter::HandleIcmpReceive(void * aContext,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
const otIcmp6Header *aIcmpHeader)
|
||||
{
|
||||
static_cast<Interpreter *>(aContext)->HandleIcmpReceive(*static_cast<Message *>(aMessage),
|
||||
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
|
||||
*static_cast<const Ip6::IcmpHeader *>(aIcmpHeader));
|
||||
static_cast<Interpreter *>(aContext)->HandleIcmpReceive(aMessage, aMessageInfo, aIcmpHeader);
|
||||
}
|
||||
|
||||
void Interpreter::HandleIcmpReceive(Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const otIcmp6Header & aIcmpHeader)
|
||||
void Interpreter::HandleIcmpReceive(otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
const otIcmp6Header *aIcmpHeader)
|
||||
{
|
||||
uint32_t timestamp = 0;
|
||||
uint32_t timestamp;
|
||||
|
||||
VerifyOrExit(aIcmpHeader.mType == OT_ICMP6_TYPE_ECHO_REPLY);
|
||||
VerifyOrExit(aIcmpHeader->mType == OT_ICMP6_TYPE_ECHO_REPLY);
|
||||
VerifyOrExit((mPingIdentifier != 0) && (mPingIdentifier == HostSwap16(aIcmpHeader->mData.m16[0])));
|
||||
|
||||
mServer->OutputFormat("%u bytes from ",
|
||||
aMessage.GetLength() - aMessage.GetOffset() + static_cast<uint16_t>(sizeof(otIcmp6Header)));
|
||||
mServer->OutputFormat("%u bytes from ", otMessageGetLength(aMessage) - otMessageGetOffset(aMessage) +
|
||||
static_cast<uint16_t>(sizeof(otIcmp6Header)));
|
||||
|
||||
OutputIp6Address(aMessageInfo.GetPeerAddr());
|
||||
OutputIp6Address(aMessageInfo->mPeerAddr);
|
||||
|
||||
mServer->OutputFormat(": icmp_seq=%d hlim=%d", HostSwap16(aIcmpHeader.mData.m16[1]), aMessageInfo.mHopLimit);
|
||||
mServer->OutputFormat(": icmp_seq=%d hlim=%d", HostSwap16(aIcmpHeader->mData.m16[1]), aMessageInfo->mHopLimit);
|
||||
|
||||
if (aMessage.Read(aMessage.GetOffset(), sizeof(uint32_t), ×tamp) >= static_cast<int>(sizeof(uint32_t)))
|
||||
if (otMessageRead(aMessage, otMessageGetOffset(aMessage), ×tamp, sizeof(uint32_t)) == sizeof(uint32_t))
|
||||
{
|
||||
mServer->OutputFormat(" time=%dms", TimerMilli::GetNow().GetValue() - HostSwap32(timestamp));
|
||||
}
|
||||
@@ -2025,26 +2027,21 @@ void Interpreter::ProcessPing(int argc, char *argv[])
|
||||
|
||||
if (strcmp(argv[0], "stop") == 0)
|
||||
{
|
||||
if (!mPingTimer.IsRunning())
|
||||
{
|
||||
error = OT_ERROR_INVALID_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mPingTimer.Stop();
|
||||
}
|
||||
|
||||
mPingIdentifier = 0;
|
||||
VerifyOrExit(mPingTimer.IsRunning(), error = OT_ERROR_INVALID_STATE);
|
||||
mPingTimer.Stop();
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
VerifyOrExit(!mPingTimer.IsRunning(), error = OT_ERROR_BUSY);
|
||||
|
||||
mMessageInfo = Ip6::MessageInfo();
|
||||
SuccessOrExit(error = mMessageInfo.GetPeerAddr().FromString(argv[0]));
|
||||
SuccessOrExit(error = otIp6AddressFromString(argv[0], &mPingDestAddress));
|
||||
|
||||
mLength = 8;
|
||||
mCount = 1;
|
||||
mInterval = 1000;
|
||||
mPingLength = kDefaultPingLength;
|
||||
mPingCount = kDefaultPingCount;
|
||||
mPingInterval = kDefaultPingInterval;
|
||||
mPingHopLimit = 0;
|
||||
mPingAllowZeroHopLimit = false;
|
||||
|
||||
while (index < argc)
|
||||
{
|
||||
@@ -2052,28 +2049,25 @@ void Interpreter::ProcessPing(int argc, char *argv[])
|
||||
{
|
||||
case 1:
|
||||
SuccessOrExit(error = ParseLong(argv[index], value));
|
||||
mLength = static_cast<uint16_t>(value);
|
||||
mPingLength = static_cast<uint16_t>(value);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
SuccessOrExit(error = ParseLong(argv[index], value));
|
||||
mCount = static_cast<uint16_t>(value);
|
||||
mPingCount = static_cast<uint16_t>(value);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
SuccessOrExit(error = ParsePingInterval(argv[index], interval));
|
||||
VerifyOrExit(0 < interval && interval <= Timer::kMaxDelay, error = OT_ERROR_INVALID_ARGS);
|
||||
mInterval = interval;
|
||||
mPingInterval = interval;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
SuccessOrExit(error = ParseLong(argv[index], value));
|
||||
VerifyOrExit(0 <= value && value <= 255, error = OT_ERROR_INVALID_ARGS);
|
||||
mMessageInfo.mHopLimit = static_cast<uint8_t>(value);
|
||||
if (value == 0)
|
||||
{
|
||||
mMessageInfo.mAllowZeroHopLimit = true;
|
||||
}
|
||||
mPingHopLimit = static_cast<uint8_t>(value);
|
||||
mPingAllowZeroHopLimit = (mPingHopLimit == 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2083,42 +2077,56 @@ void Interpreter::ProcessPing(int argc, char *argv[])
|
||||
index++;
|
||||
}
|
||||
|
||||
HandlePingTimer();
|
||||
mPingIdentifier++;
|
||||
|
||||
return;
|
||||
if (mPingIdentifier == 0)
|
||||
{
|
||||
mPingIdentifier++;
|
||||
}
|
||||
|
||||
SendPing();
|
||||
|
||||
exit:
|
||||
AppendResult(error);
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
AppendResult(error);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::HandlePingTimer(Timer &aTimer)
|
||||
{
|
||||
GetOwner(aTimer).HandlePingTimer();
|
||||
GetOwner(aTimer).SendPing();
|
||||
}
|
||||
|
||||
void Interpreter::HandlePingTimer()
|
||||
void Interpreter::SendPing(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint32_t timestamp = HostSwap32(TimerMilli::GetNow().GetValue());
|
||||
uint32_t timestamp = HostSwap32(TimerMilli::GetNow().GetValue());
|
||||
otMessage * message = NULL;
|
||||
otMessageInfo messageInfo;
|
||||
|
||||
otMessage * message;
|
||||
const otMessageInfo *messageInfo = static_cast<const otMessageInfo *>(&mMessageInfo);
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
messageInfo.mPeerAddr = mPingDestAddress;
|
||||
messageInfo.mHopLimit = mPingHopLimit;
|
||||
messageInfo.mAllowZeroHopLimit = mPingAllowZeroHopLimit;
|
||||
|
||||
VerifyOrExit((message = otIp6NewMessage(mInstance, NULL)) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
SuccessOrExit(error = otMessageAppend(message, ×tamp, sizeof(timestamp)));
|
||||
SuccessOrExit(error = otMessageSetLength(message, mLength));
|
||||
SuccessOrExit(error = otIcmp6SendEchoRequest(mInstance, message, messageInfo, 1));
|
||||
message = otIp6NewMessage(mInstance, NULL);
|
||||
VerifyOrExit(message != NULL);
|
||||
|
||||
SuccessOrExit(otMessageAppend(message, ×tamp, sizeof(timestamp)));
|
||||
SuccessOrExit(otMessageSetLength(message, mPingLength));
|
||||
SuccessOrExit(otIcmp6SendEchoRequest(mInstance, message, &messageInfo, mPingIdentifier));
|
||||
|
||||
message = NULL;
|
||||
|
||||
exit:
|
||||
|
||||
if (error != OT_ERROR_NONE && message != NULL)
|
||||
if (message != NULL)
|
||||
{
|
||||
otMessageFree(message);
|
||||
}
|
||||
|
||||
if (--mCount)
|
||||
if (--mPingCount)
|
||||
{
|
||||
mPingTimer.Start(mInterval);
|
||||
mPingTimer.Start(mPingInterval);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user