Modifying the ping command
1、Round trip times in the ping command range from millisecond to subtle 2、Add statistics on RTT related min/avg/Max/mdev in ping program 3、The ping command supports ctrl+c interruption operations Signed-off-by: xuewenliang <xuewenliang@xiaomi.com>
This commit is contained in:
parent
2796187bdf
commit
c69ec94d13
@ -79,7 +79,7 @@ struct ping_info_s
|
|||||||
struct ping_result_s
|
struct ping_result_s
|
||||||
{
|
{
|
||||||
int code; /* Notice code ICMP_I/E/W_XXX */
|
int code; /* Notice code ICMP_I/E/W_XXX */
|
||||||
int extra; /* Extra information for code */
|
long extra; /* Extra information for code */
|
||||||
struct in_addr dest; /* Target address to ping */
|
struct in_addr dest; /* Target address to ping */
|
||||||
uint16_t nrequests; /* Number of ICMP ECHO requests sent */
|
uint16_t nrequests; /* Number of ICMP ECHO requests sent */
|
||||||
uint16_t nreplies; /* Number of matching ICMP ECHO replies received */
|
uint16_t nreplies; /* Number of matching ICMP ECHO replies received */
|
||||||
|
@ -79,7 +79,7 @@ struct ping6_info_s
|
|||||||
struct ping6_result_s
|
struct ping6_result_s
|
||||||
{
|
{
|
||||||
int code; /* Notice code ICMPv6_I/E/W_XXX */
|
int code; /* Notice code ICMPv6_I/E/W_XXX */
|
||||||
int extra; /* Extra information for code */
|
long extra; /* Extra information for code */
|
||||||
struct in6_addr dest; /* Target address to ping */
|
struct in6_addr dest; /* Target address to ping */
|
||||||
uint16_t nrequests; /* Number of ICMP ECHO requests sent */
|
uint16_t nrequests; /* Number of ICMP ECHO requests sent */
|
||||||
uint16_t nreplies; /* Number of matching ICMP ECHO replies received */
|
uint16_t nreplies; /* Number of matching ICMP ECHO replies received */
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef CONFIG_LIBC_NETDB
|
#ifdef CONFIG_LIBC_NETDB
|
||||||
# include <netdb.h>
|
# include <netdb.h>
|
||||||
@ -58,12 +60,22 @@
|
|||||||
* separate instance of g_pingid in every process space.
|
* separate instance of g_pingid in every process space.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static uint16_t g_pingid = 0;
|
static uint16_t g_pingid;
|
||||||
|
static volatile bool g_exiting;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sigexit
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void sigexit(int signo)
|
||||||
|
{
|
||||||
|
g_exiting = true;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: ping_newid
|
* Name: ping_newid
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -136,7 +148,7 @@ static int ping_gethostip(FAR const char *hostname, FAR struct in_addr *dest)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void icmp_callback(FAR struct ping_result_s *result,
|
static void icmp_callback(FAR struct ping_result_s *result,
|
||||||
int code, int extra)
|
int code, long extra)
|
||||||
{
|
{
|
||||||
result->code = code;
|
result->code = code;
|
||||||
result->extra = extra;
|
result->extra = extra;
|
||||||
@ -161,7 +173,7 @@ void icmp_ping(FAR const struct ping_info_s *info)
|
|||||||
struct pollfd recvfd;
|
struct pollfd recvfd;
|
||||||
FAR uint8_t *iobuffer;
|
FAR uint8_t *iobuffer;
|
||||||
FAR uint8_t *ptr;
|
FAR uint8_t *ptr;
|
||||||
int32_t elapsed;
|
long elapsed;
|
||||||
clock_t kickoff;
|
clock_t kickoff;
|
||||||
clock_t start;
|
clock_t start;
|
||||||
socklen_t addrlen;
|
socklen_t addrlen;
|
||||||
@ -173,6 +185,9 @@ void icmp_ping(FAR const struct ping_info_s *info)
|
|||||||
int ch;
|
int ch;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
g_exiting = false;
|
||||||
|
signal(SIGINT, sigexit);
|
||||||
|
|
||||||
/* Initialize result structure */
|
/* Initialize result structure */
|
||||||
|
|
||||||
memset(&result, 0, sizeof(result));
|
memset(&result, 0, sizeof(result));
|
||||||
@ -218,6 +233,11 @@ void icmp_ping(FAR const struct ping_info_s *info)
|
|||||||
|
|
||||||
while (result.nrequests < info->count)
|
while (result.nrequests < info->count)
|
||||||
{
|
{
|
||||||
|
if (g_exiting)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy the ICMP header into the I/O buffer */
|
/* Copy the ICMP header into the I/O buffer */
|
||||||
|
|
||||||
memcpy(iobuffer, &outhdr, sizeof(struct icmp_hdr_s));
|
memcpy(iobuffer, &outhdr, sizeof(struct icmp_hdr_s));
|
||||||
@ -262,7 +282,7 @@ void icmp_ping(FAR const struct ping_info_s *info)
|
|||||||
recvfd.events = POLLIN;
|
recvfd.events = POLLIN;
|
||||||
recvfd.revents = 0;
|
recvfd.revents = 0;
|
||||||
|
|
||||||
ret = poll(&recvfd, 1, info->timeout - elapsed);
|
ret = poll(&recvfd, 1, info->timeout - elapsed / USEC_PER_MSEC);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
icmp_callback(&result, ICMP_E_POLL, errno);
|
icmp_callback(&result, ICMP_E_POLL, errno);
|
||||||
@ -290,7 +310,7 @@ void icmp_ping(FAR const struct ping_info_s *info)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed = (unsigned int)TICK2MSEC(clock() - start);
|
elapsed = TICK2USEC(clock() - start);
|
||||||
inhdr = (FAR struct icmp_hdr_s *)iobuffer;
|
inhdr = (FAR struct icmp_hdr_s *)iobuffer;
|
||||||
|
|
||||||
if (inhdr->type == ICMP_ECHO_REPLY)
|
if (inhdr->type == ICMP_ECHO_REPLY)
|
||||||
@ -309,13 +329,13 @@ void icmp_ping(FAR const struct ping_info_s *info)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool verified = true;
|
bool verified = true;
|
||||||
int32_t pktdelay = elapsed;
|
long pktdelay = elapsed;
|
||||||
|
|
||||||
if (ntohs(inhdr->seqno) < result.seqno)
|
if (ntohs(inhdr->seqno) < result.seqno)
|
||||||
{
|
{
|
||||||
icmp_callback(&result, ICMP_W_SEQNOSMALL,
|
icmp_callback(&result, ICMP_W_SEQNOSMALL,
|
||||||
ntohs(inhdr->seqno));
|
ntohs(inhdr->seqno));
|
||||||
pktdelay += info->delay;
|
pktdelay += info->delay * USEC_PER_MSEC;
|
||||||
retry = true;
|
retry = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,11 +382,12 @@ void icmp_ping(FAR const struct ping_info_s *info)
|
|||||||
icmp_callback(&result, ICMP_W_TYPE, inhdr->type);
|
icmp_callback(&result, ICMP_W_TYPE, inhdr->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (retry && info->delay > elapsed && info->timeout > elapsed);
|
while (retry && info->delay > elapsed / USEC_PER_MSEC &&
|
||||||
|
info->timeout > elapsed / USEC_PER_MSEC);
|
||||||
|
|
||||||
/* Wait if necessary to preserved the requested ping rate */
|
/* Wait if necessary to preserved the requested ping rate */
|
||||||
|
|
||||||
elapsed = (unsigned int)TICK2MSEC(clock() - start);
|
elapsed = TICK2MSEC(clock() - start);
|
||||||
if (elapsed < info->delay)
|
if (elapsed < info->delay)
|
||||||
{
|
{
|
||||||
struct timespec rqt;
|
struct timespec rqt;
|
||||||
@ -388,7 +409,7 @@ void icmp_ping(FAR const struct ping_info_s *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
icmp_callback(&result, ICMP_I_FINISH, TICK2MSEC(clock() - kickoff));
|
icmp_callback(&result, ICMP_I_FINISH, TICK2USEC(clock() - kickoff));
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
free(iobuffer);
|
free(iobuffer);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef CONFIG_LIBC_NETDB
|
#ifdef CONFIG_LIBC_NETDB
|
||||||
# include <netdb.h>
|
# include <netdb.h>
|
||||||
@ -57,12 +59,22 @@
|
|||||||
* separate instance of g_ping6_id in every process space.
|
* separate instance of g_ping6_id in every process space.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static uint16_t g_ping6_id = 0;
|
static uint16_t g_ping6_id;
|
||||||
|
static volatile bool g_exiting6;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sigexit
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void sigexit(int signo)
|
||||||
|
{
|
||||||
|
g_exiting6 = true;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: ping6_newid
|
* Name: ping6_newid
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -135,7 +147,7 @@ static int ping6_gethostip(FAR const char *hostname,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void icmp6_callback(FAR struct ping6_result_s *result,
|
static void icmp6_callback(FAR struct ping6_result_s *result,
|
||||||
int code, int extra)
|
int code, long extra)
|
||||||
{
|
{
|
||||||
result->code = code;
|
result->code = code;
|
||||||
result->extra = extra;
|
result->extra = extra;
|
||||||
@ -160,7 +172,7 @@ void icmp6_ping(FAR const struct ping6_info_s *info)
|
|||||||
struct pollfd recvfd;
|
struct pollfd recvfd;
|
||||||
FAR uint8_t *iobuffer;
|
FAR uint8_t *iobuffer;
|
||||||
FAR uint8_t *ptr;
|
FAR uint8_t *ptr;
|
||||||
int32_t elapsed;
|
long elapsed;
|
||||||
clock_t kickoff;
|
clock_t kickoff;
|
||||||
clock_t start;
|
clock_t start;
|
||||||
socklen_t addrlen;
|
socklen_t addrlen;
|
||||||
@ -172,6 +184,9 @@ void icmp6_ping(FAR const struct ping6_info_s *info)
|
|||||||
int ch;
|
int ch;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
g_exiting6 = false;
|
||||||
|
signal(SIGINT, sigexit);
|
||||||
|
|
||||||
/* Initialize result structure */
|
/* Initialize result structure */
|
||||||
|
|
||||||
memset(&result, 0, sizeof(result));
|
memset(&result, 0, sizeof(result));
|
||||||
@ -217,6 +232,11 @@ void icmp6_ping(FAR const struct ping6_info_s *info)
|
|||||||
|
|
||||||
while (result.nrequests < info->count)
|
while (result.nrequests < info->count)
|
||||||
{
|
{
|
||||||
|
if (g_exiting6)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy the ICMP header into the I/O buffer */
|
/* Copy the ICMP header into the I/O buffer */
|
||||||
|
|
||||||
memcpy(iobuffer, &outhdr, SIZEOF_ICMPV6_ECHO_REQUEST_S(0));
|
memcpy(iobuffer, &outhdr, SIZEOF_ICMPV6_ECHO_REQUEST_S(0));
|
||||||
@ -261,7 +281,7 @@ void icmp6_ping(FAR const struct ping6_info_s *info)
|
|||||||
recvfd.events = POLLIN;
|
recvfd.events = POLLIN;
|
||||||
recvfd.revents = 0;
|
recvfd.revents = 0;
|
||||||
|
|
||||||
ret = poll(&recvfd, 1, info->timeout - elapsed);
|
ret = poll(&recvfd, 1, info->timeout - elapsed / USEC_PER_MSEC);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
icmp6_callback(&result, ICMPv6_E_POLL, errno);
|
icmp6_callback(&result, ICMPv6_E_POLL, errno);
|
||||||
@ -289,7 +309,7 @@ void icmp6_ping(FAR const struct ping6_info_s *info)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed = (unsigned int)TICK2MSEC(clock() - start);
|
elapsed = TICK2USEC(clock() - start);
|
||||||
inhdr = (FAR struct icmpv6_echo_reply_s *)iobuffer;
|
inhdr = (FAR struct icmpv6_echo_reply_s *)iobuffer;
|
||||||
|
|
||||||
if (inhdr->type == ICMPv6_ECHO_REPLY)
|
if (inhdr->type == ICMPv6_ECHO_REPLY)
|
||||||
@ -308,13 +328,13 @@ void icmp6_ping(FAR const struct ping6_info_s *info)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool verified = true;
|
bool verified = true;
|
||||||
int32_t pktdelay = elapsed;
|
long pktdelay = elapsed;
|
||||||
|
|
||||||
if (ntohs(inhdr->seqno) < result.seqno)
|
if (ntohs(inhdr->seqno) < result.seqno)
|
||||||
{
|
{
|
||||||
icmp6_callback(&result, ICMPv6_W_SEQNOSMALL,
|
icmp6_callback(&result, ICMPv6_W_SEQNOSMALL,
|
||||||
ntohs(inhdr->seqno));
|
ntohs(inhdr->seqno));
|
||||||
pktdelay += info->delay;
|
pktdelay += info->delay * USEC_PER_MSEC;
|
||||||
retry = true;
|
retry = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,11 +381,12 @@ void icmp6_ping(FAR const struct ping6_info_s *info)
|
|||||||
icmp6_callback(&result, ICMPv6_W_TYPE, inhdr->type);
|
icmp6_callback(&result, ICMPv6_W_TYPE, inhdr->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (retry && info->delay > elapsed && info->timeout > elapsed);
|
while (retry && info->delay > elapsed / USEC_PER_MSEC &&
|
||||||
|
info->timeout > elapsed / USEC_PER_MSEC);
|
||||||
|
|
||||||
/* Wait if necessary to preserved the requested ping rate */
|
/* Wait if necessary to preserved the requested ping rate */
|
||||||
|
|
||||||
elapsed = (unsigned int)TICK2MSEC(clock() - start);
|
elapsed = TICK2MSEC(clock() - start);
|
||||||
if (elapsed < info->delay)
|
if (elapsed < info->delay)
|
||||||
{
|
{
|
||||||
struct timespec rqt;
|
struct timespec rqt;
|
||||||
@ -387,7 +408,7 @@ void icmp6_ping(FAR const struct ping6_info_s *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
icmp6_callback(&result, ICMPv6_I_FINISH, TICK2MSEC(clock() - kickoff));
|
icmp6_callback(&result, ICMPv6_I_FINISH, TICK2USEC(clock() - kickoff));
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
free(iobuffer);
|
free(iobuffer);
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,16 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
#include <nuttx/clock.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <nuttx/lib/math.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <fixedmath.h>
|
||||||
|
|
||||||
#include "netutils/icmp_ping.h"
|
#include "netutils/icmp_ping.h"
|
||||||
|
|
||||||
@ -48,6 +52,10 @@
|
|||||||
struct ping_priv_s
|
struct ping_priv_s
|
||||||
{
|
{
|
||||||
int code; /* Notice code ICMP_I/E/W_XXX */
|
int code; /* Notice code ICMP_I/E/W_XXX */
|
||||||
|
long tmin; /* Minimum round trip time */
|
||||||
|
long tmax; /* Maximum round trip time */
|
||||||
|
long long tsum; /* Sum of all times, for doing average */
|
||||||
|
long long tsum2; /* Sum2 is the sum of the squares of sum ,for doing mean deviation */
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -118,7 +126,7 @@ static void ping_result(FAR const struct ping_result_s *result)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_E_SOCKET:
|
case ICMP_E_SOCKET:
|
||||||
fprintf(stderr, "ERROR: socket() failed: %d\n", result->extra);
|
fprintf(stderr, "ERROR: socket() failed: %ld\n", result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_I_BEGIN:
|
case ICMP_I_BEGIN:
|
||||||
@ -131,21 +139,21 @@ static void ping_result(FAR const struct ping_result_s *result)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_E_SENDTO:
|
case ICMP_E_SENDTO:
|
||||||
fprintf(stderr, "ERROR: sendto failed at seqno %u: %d\n",
|
fprintf(stderr, "ERROR: sendto failed at seqno %u: %ld\n",
|
||||||
result->seqno, result->extra);
|
result->seqno, result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_E_SENDSMALL:
|
case ICMP_E_SENDSMALL:
|
||||||
fprintf(stderr, "ERROR: sendto returned %d, expected %u\n",
|
fprintf(stderr, "ERROR: sendto returned %ld, expected %u\n",
|
||||||
result->extra, result->outsize);
|
result->extra, result->outsize);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_E_POLL:
|
case ICMP_E_POLL:
|
||||||
fprintf(stderr, "ERROR: poll failed: %d\n", result->extra);
|
fprintf(stderr, "ERROR: poll failed: %ld\n", result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_W_TIMEOUT:
|
case ICMP_W_TIMEOUT:
|
||||||
printf("No response from %u.%u.%u.%u: icmp_seq=%u time=%d ms\n",
|
printf("No response from %u.%u.%u.%u: icmp_seq=%u time=%ld ms\n",
|
||||||
(unsigned int)(result->dest.s_addr) & 0xff,
|
(unsigned int)(result->dest.s_addr) & 0xff,
|
||||||
(unsigned int)(result->dest.s_addr >> 8) & 0xff,
|
(unsigned int)(result->dest.s_addr >> 8) & 0xff,
|
||||||
(unsigned int)(result->dest.s_addr >> 16) & 0xff,
|
(unsigned int)(result->dest.s_addr >> 16) & 0xff,
|
||||||
@ -154,23 +162,23 @@ static void ping_result(FAR const struct ping_result_s *result)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_E_RECVFROM:
|
case ICMP_E_RECVFROM:
|
||||||
fprintf(stderr, "ERROR: recvfrom failed: %d\n", result->extra);
|
fprintf(stderr, "ERROR: recvfrom failed: %ld\n", result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_E_RECVSMALL:
|
case ICMP_E_RECVSMALL:
|
||||||
fprintf(stderr, "ERROR: short ICMP packet: %d\n", result->extra);
|
fprintf(stderr, "ERROR: short ICMP packet: %ld\n", result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_W_IDDIFF:
|
case ICMP_W_IDDIFF:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"WARNING: Ignoring ICMP reply with ID %d. "
|
"WARNING: Ignoring ICMP reply with ID %ld. "
|
||||||
"Expected %u\n",
|
"Expected %u\n",
|
||||||
result->extra, result->id);
|
result->extra, result->id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_W_SEQNOBIG:
|
case ICMP_W_SEQNOBIG:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"WARNING: Ignoring ICMP reply to sequence %d. "
|
"WARNING: Ignoring ICMP reply to sequence %ld. "
|
||||||
"Expected <= %u\n",
|
"Expected <= %u\n",
|
||||||
result->extra, result->seqno);
|
result->extra, result->seqno);
|
||||||
break;
|
break;
|
||||||
@ -180,19 +188,32 @@ static void ping_result(FAR const struct ping_result_s *result)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_I_ROUNDTRIP:
|
case ICMP_I_ROUNDTRIP:
|
||||||
printf("%u bytes from %u.%u.%u.%u: icmp_seq=%u time=%d ms\n",
|
priv->tsum += result->extra;
|
||||||
|
priv->tsum2 += (long long)result->extra * result->extra;
|
||||||
|
if (result->extra < priv->tmin)
|
||||||
|
{
|
||||||
|
priv->tmin = result->extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result->extra > priv->tmax)
|
||||||
|
{
|
||||||
|
priv->tmax = result->extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%u bytes from %u.%u.%u.%u: icmp_seq=%u time=%ld.%ld ms\n",
|
||||||
result->info->datalen,
|
result->info->datalen,
|
||||||
(unsigned int)(result->dest.s_addr) & 0xff,
|
(unsigned int)(result->dest.s_addr) & 0xff,
|
||||||
(unsigned int)(result->dest.s_addr >> 8) & 0xff,
|
(unsigned int)(result->dest.s_addr >> 8) & 0xff,
|
||||||
(unsigned int)(result->dest.s_addr >> 16) & 0xff,
|
(unsigned int)(result->dest.s_addr >> 16) & 0xff,
|
||||||
(unsigned int)(result->dest.s_addr >> 24) & 0xff,
|
(unsigned int)(result->dest.s_addr >> 24) & 0xff,
|
||||||
result->seqno, result->extra);
|
result->seqno, result->extra / USEC_PER_MSEC,
|
||||||
|
result->extra % USEC_PER_MSEC / MSEC_PER_DSEC);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_W_RECVBIG:
|
case ICMP_W_RECVBIG:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"WARNING: Ignoring ICMP reply with different payload "
|
"WARNING: Ignoring ICMP reply with different payload "
|
||||||
"size: %d vs %u\n",
|
"size: %ld vs %u\n",
|
||||||
result->extra, result->outsize);
|
result->extra, result->outsize);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -201,7 +222,7 @@ static void ping_result(FAR const struct ping_result_s *result)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMP_W_TYPE:
|
case ICMP_W_TYPE:
|
||||||
fprintf(stderr, "WARNING: ICMP packet with unknown type: %d\n",
|
fprintf(stderr, "WARNING: ICMP packet with unknown type: %ld\n",
|
||||||
result->extra);
|
result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -217,8 +238,25 @@ static void ping_result(FAR const struct ping_result_s *result)
|
|||||||
result->nrequests;
|
result->nrequests;
|
||||||
|
|
||||||
printf("%u packets transmitted, %u received, %u%% packet loss, "
|
printf("%u packets transmitted, %u received, %u%% packet loss, "
|
||||||
"time %d ms\n",
|
"time %ld ms\n",
|
||||||
result->nrequests, result->nreplies, tmp, result->extra);
|
result->nrequests, result->nreplies, tmp,
|
||||||
|
result->extra / USEC_PER_MSEC);
|
||||||
|
if (result->nreplies > 0)
|
||||||
|
{
|
||||||
|
long avg = priv->tsum / result->nreplies;
|
||||||
|
long long tempnum = priv->tsum2 / result->nreplies -
|
||||||
|
(long long)avg * avg;
|
||||||
|
long tmdev = ub16toi(ub32sqrtub16(uitoub32(tempnum)));
|
||||||
|
|
||||||
|
printf("rtt min/avg/max/mdev = %ld.%03ld/%ld.%03ld/"
|
||||||
|
"%ld.%03ld/%ld.%03ld ms\n",
|
||||||
|
priv->tmin / USEC_PER_MSEC,
|
||||||
|
priv->tmin % USEC_PER_MSEC,
|
||||||
|
avg / USEC_PER_MSEC, avg % USEC_PER_MSEC,
|
||||||
|
priv->tmax / USEC_PER_MSEC,
|
||||||
|
priv->tmax % USEC_PER_MSEC,
|
||||||
|
tmdev / USEC_PER_MSEC, tmdev % USEC_PER_MSEC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -243,6 +281,10 @@ int main(int argc, FAR char *argv[])
|
|||||||
info.callback = ping_result;
|
info.callback = ping_result;
|
||||||
info.priv = &priv;
|
info.priv = &priv;
|
||||||
priv.code = ICMP_I_OK;
|
priv.code = ICMP_I_OK;
|
||||||
|
priv.tmin = LONG_MAX;
|
||||||
|
priv.tmax = 0;
|
||||||
|
priv.tsum = 0;
|
||||||
|
priv.tsum2 = 0;
|
||||||
|
|
||||||
/* Parse command line options */
|
/* Parse command line options */
|
||||||
|
|
||||||
|
@ -23,12 +23,16 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
#include <nuttx/clock.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <nuttx/lib/math.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <fixedmath.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
@ -50,6 +54,10 @@
|
|||||||
struct ping6_priv_s
|
struct ping6_priv_s
|
||||||
{
|
{
|
||||||
int code; /* Notice code ICMP_I/E/W_XXX */
|
int code; /* Notice code ICMP_I/E/W_XXX */
|
||||||
|
long tmin; /* Minimum round trip time */
|
||||||
|
long tmax; /* Maximum round trip time */
|
||||||
|
long long tsum; /* Sum of all times, for doing average */
|
||||||
|
long long tsum2; /* Sum2 is the sum of the squares of sum ,for doing mean deviation */
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -121,7 +129,7 @@ static void ping6_result(FAR const struct ping6_result_s *result)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_E_SOCKET:
|
case ICMPv6_E_SOCKET:
|
||||||
fprintf(stderr, "ERROR: socket() failed: %d\n", result->extra);
|
fprintf(stderr, "ERROR: socket() failed: %ld\n", result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_I_BEGIN:
|
case ICMPv6_I_BEGIN:
|
||||||
@ -132,44 +140,44 @@ static void ping6_result(FAR const struct ping6_result_s *result)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_E_SENDTO:
|
case ICMPv6_E_SENDTO:
|
||||||
fprintf(stderr, "ERROR: sendto failed at seqno %u: %d\n",
|
fprintf(stderr, "ERROR: sendto failed at seqno %u: %ld\n",
|
||||||
result->seqno, result->extra);
|
result->seqno, result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_E_SENDSMALL:
|
case ICMPv6_E_SENDSMALL:
|
||||||
fprintf(stderr, "ERROR: sendto returned %d, expected %u\n",
|
fprintf(stderr, "ERROR: sendto returned %ld, expected %u\n",
|
||||||
result->extra, result->outsize);
|
result->extra, result->outsize);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_E_POLL:
|
case ICMPv6_E_POLL:
|
||||||
fprintf(stderr, "ERROR: poll failed: %d\n", result->extra);
|
fprintf(stderr, "ERROR: poll failed: %ld\n", result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_W_TIMEOUT:
|
case ICMPv6_W_TIMEOUT:
|
||||||
inet_ntop(AF_INET6, result->dest.s6_addr16, strbuffer,
|
inet_ntop(AF_INET6, result->dest.s6_addr16, strbuffer,
|
||||||
INET6_ADDRSTRLEN);
|
INET6_ADDRSTRLEN);
|
||||||
printf("No response from %s: icmp_seq=%u time=%d ms\n",
|
printf("No response from %s: icmp_seq=%u time=%ld ms\n",
|
||||||
strbuffer, result->seqno, result->extra);
|
strbuffer, result->seqno, result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_E_RECVFROM:
|
case ICMPv6_E_RECVFROM:
|
||||||
fprintf(stderr, "ERROR: recvfrom failed: %d\n", result->extra);
|
fprintf(stderr, "ERROR: recvfrom failed: %ld\n", result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_E_RECVSMALL:
|
case ICMPv6_E_RECVSMALL:
|
||||||
fprintf(stderr, "ERROR: short ICMP packet: %d\n", result->extra);
|
fprintf(stderr, "ERROR: short ICMP packet: %ld\n", result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_W_IDDIFF:
|
case ICMPv6_W_IDDIFF:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"WARNING: Ignoring ICMP reply with ID %d. "
|
"WARNING: Ignoring ICMP reply with ID %ld. "
|
||||||
"Expected %u\n",
|
"Expected %u\n",
|
||||||
result->extra, result->id);
|
result->extra, result->id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_W_SEQNOBIG:
|
case ICMPv6_W_SEQNOBIG:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"WARNING: Ignoring ICMP reply to sequence %d. "
|
"WARNING: Ignoring ICMP reply to sequence %ld. "
|
||||||
"Expected <= %u\n",
|
"Expected <= %u\n",
|
||||||
result->extra, result->seqno);
|
result->extra, result->seqno);
|
||||||
break;
|
break;
|
||||||
@ -179,17 +187,30 @@ static void ping6_result(FAR const struct ping6_result_s *result)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_I_ROUNDTRIP:
|
case ICMPv6_I_ROUNDTRIP:
|
||||||
|
priv->tsum += result->extra;
|
||||||
|
priv->tsum2 += (long long)result->extra * result->extra;
|
||||||
|
if (result->extra < priv->tmin)
|
||||||
|
{
|
||||||
|
priv->tmin = result->extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result->extra > priv->tmax)
|
||||||
|
{
|
||||||
|
priv->tmax = result->extra;
|
||||||
|
}
|
||||||
|
|
||||||
inet_ntop(AF_INET6, result->dest.s6_addr16, strbuffer,
|
inet_ntop(AF_INET6, result->dest.s6_addr16, strbuffer,
|
||||||
INET6_ADDRSTRLEN);
|
INET6_ADDRSTRLEN);
|
||||||
printf("%u bytes from %s icmp_seq=%u time=%u ms\n",
|
printf("%u bytes from %s icmp_seq=%u time=%ld.%ld ms\n",
|
||||||
result->info->datalen, strbuffer, result->seqno,
|
result->info->datalen, strbuffer, result->seqno,
|
||||||
result->extra);
|
result->extra / USEC_PER_MSEC,
|
||||||
|
result->extra % USEC_PER_MSEC / MSEC_PER_DSEC);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_W_RECVBIG:
|
case ICMPv6_W_RECVBIG:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"WARNING: Ignoring ICMP reply with different payload "
|
"WARNING: Ignoring ICMP reply with different payload "
|
||||||
"size: %d vs %u\n",
|
"size: %ld vs %u\n",
|
||||||
result->extra, result->outsize);
|
result->extra, result->outsize);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -198,7 +219,7 @@ static void ping6_result(FAR const struct ping6_result_s *result)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ICMPv6_W_TYPE:
|
case ICMPv6_W_TYPE:
|
||||||
fprintf(stderr, "WARNING: ICMP packet with unknown type: %d\n",
|
fprintf(stderr, "WARNING: ICMP packet with unknown type: %ld\n",
|
||||||
result->extra);
|
result->extra);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -213,9 +234,26 @@ static void ping6_result(FAR const struct ping6_result_s *result)
|
|||||||
(result->nrequests >> 1)) /
|
(result->nrequests >> 1)) /
|
||||||
result->nrequests;
|
result->nrequests;
|
||||||
|
|
||||||
printf("%u packets transmitted, %u received, "
|
printf("%u packets transmitted, %u received, %u%% packet loss,"
|
||||||
"%u%% packet loss, time %d ms\n",
|
"time %ld ms\n",
|
||||||
result->nrequests, result->nreplies, tmp, result->extra);
|
result->nrequests, result->nreplies, tmp,
|
||||||
|
result->extra / USEC_PER_MSEC);
|
||||||
|
if (result->nreplies > 0)
|
||||||
|
{
|
||||||
|
long avg = priv->tsum / result->nreplies;
|
||||||
|
long long tempnum = priv->tsum2 / result->nreplies -
|
||||||
|
(long long)avg * avg;
|
||||||
|
long tmdev = ub16toi(ub32sqrtub16(uitoub32(tempnum)));
|
||||||
|
|
||||||
|
printf("rtt min/avg/max/mdev = %ld.%03ld/%ld.%03ld/"
|
||||||
|
"%ld.%03ld/%ld.%03ld ms\n",
|
||||||
|
priv->tmin / USEC_PER_MSEC,
|
||||||
|
priv->tmin % USEC_PER_MSEC,
|
||||||
|
avg / USEC_PER_MSEC, avg % USEC_PER_MSEC,
|
||||||
|
priv->tmax / USEC_PER_MSEC,
|
||||||
|
priv->tmax % USEC_PER_MSEC,
|
||||||
|
tmdev / USEC_PER_MSEC, tmdev % USEC_PER_MSEC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -240,6 +278,10 @@ int main(int argc, FAR char *argv[])
|
|||||||
info.callback = ping6_result;
|
info.callback = ping6_result;
|
||||||
info.priv = &priv;
|
info.priv = &priv;
|
||||||
priv.code = ICMPv6_I_OK;
|
priv.code = ICMPv6_I_OK;
|
||||||
|
priv.tmin = LONG_MAX;
|
||||||
|
priv.tmax = 0;
|
||||||
|
priv.tsum = 0;
|
||||||
|
priv.tsum2 = 0;
|
||||||
|
|
||||||
/* Parse command line options */
|
/* Parse command line options */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user