diff --git a/src/cli/README.md b/src/cli/README.md index 27ce95a1c..890e8a5ad 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -348,13 +348,13 @@ Set the IEEE 802.15.4 PAN ID value. Done ``` -### ping \ [size] +### ping \ [size] [count] [interval] Send an ICMPv6 Echo Request. ```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 +16 bytes from fdde:ad00:beef:0:558:f56b:d688:799: icmp_seq=1 hlim=64 time=28ms ``` ### prefix add \ [pvdcsr] [prf] diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index e08c333ae..a25d70ed7 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -42,6 +42,7 @@ #include using Thread::Encoding::BigEndian::HostSwap16; +using Thread::Encoding::BigEndian::HostSwap32; namespace Thread { namespace Cli { @@ -83,6 +84,10 @@ Ip6::IcmpEcho Interpreter::sIcmpEcho(&HandleEchoResponse, NULL); Ip6::SockAddr Interpreter::sSockAddr; Server *Interpreter::sServer; uint8_t Interpreter::sEchoRequest[1500]; +uint16_t Interpreter::sLength = 8; +uint16_t Interpreter::sCount = 1; +uint32_t Interpreter::sInterval = 1000; +Timer Interpreter::sPingTimer(&HandlePingTimer, NULL); int Interpreter::Hex2Bin(const char *aHex, uint8_t *aBin, uint16_t aBinLength) { @@ -557,6 +562,7 @@ exit: void Interpreter::HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { Ip6::IcmpHeader icmp6Header; + uint32_t timestamp = 0; aMessage.Read(aMessage.GetOffset(), sizeof(icmp6Header), &icmp6Header); @@ -570,26 +576,60 @@ void Interpreter::HandleEchoResponse(void *aContext, Message &aMessage, const Ip HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[5]), HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[6]), HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[7])); - sServer->OutputFormat(": icmp_seq=%d hlim=%d\r\n", icmp6Header.GetSequence(), aMessageInfo.mHopLimit); + sServer->OutputFormat(": icmp_seq=%d hlim=%d", icmp6Header.GetSequence(), aMessageInfo.mHopLimit); + + if (aMessage.Read(aMessage.GetOffset() + sizeof(icmp6Header), sizeof(uint32_t), ×tamp) >= sizeof(uint32_t)) + { + sServer->OutputFormat(" time=%dms", Timer::GetNow() - HostSwap32(timestamp)); + } + + sServer->OutputFormat("\r\n"); } void Interpreter::ProcessPing(int argc, char *argv[]) { ThreadError error = kThreadError_None; - long length = 8; + uint8_t index = 1; + long value; VerifyOrExit(argc > 0, error = kThreadError_Parse); + VerifyOrExit(!sPingTimer.IsRunning(), error = kThreadError_Busy); memset(&sSockAddr, 0, sizeof(sSockAddr)); SuccessOrExit(error = sSockAddr.GetAddress().FromString(argv[0])); sSockAddr.mScopeId = 1; - if (argc > 1) + sLength = 8; + sCount = 1; + sInterval = 1000; + + while (index < argc) { - SuccessOrExit(error = ParseLong(argv[1], length)); + SuccessOrExit(error = ParseLong(argv[index], value)); + + switch (index) + { + case 1: + sLength = (uint16_t)value; + break; + + case 2: + sCount = (uint16_t)value; + break; + + case 3: + sInterval = (uint32_t)value; + sInterval = sInterval * 1000; + break; + + default: + ExitNow(error = kThreadError_Parse); + } + + index++; } - sIcmpEcho.SendEchoRequest(sSockAddr, sEchoRequest, length); + HandlePingTimer(NULL); return; @@ -597,6 +637,18 @@ exit: AppendResult(error); } +void Interpreter::HandlePingTimer(void *aContext) +{ + *(uint32_t *)sEchoRequest = HostSwap32(Timer::GetNow()); + sIcmpEcho.SendEchoRequest(sSockAddr, sEchoRequest, sLength); + sCount--; + + if (sCount) + { + sPingTimer.Start(sInterval); + } +} + ThreadError Interpreter::ProcessPrefixAdd(int argc, char *argv[]) { ThreadError error = kThreadError_None; diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 113608d8a..a6afc297e 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -38,6 +38,7 @@ #include #include +#include namespace Thread { @@ -120,6 +121,7 @@ private: static void ProcessWhitelist(int argc, char *argv[]); static void HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + static void HandlePingTimer(void *aContext); static void HandleActiveScanResult(otActiveScanResult *aResult); static int Hex2Bin(const char *aHex, uint8_t *aBin, uint16_t aBinLength); static ThreadError ParseLong(char *argv, long &value); @@ -131,6 +133,10 @@ private: static Ip6::IcmpEcho sIcmpEcho; static Server *sServer; static uint8_t sEchoRequest[]; + static uint16_t sLength; + static uint16_t sCount; + static uint32_t sInterval; + static Timer sPingTimer; }; } // namespace Cli