ping() integrated
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@872 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
4be5ae53a0
commit
63c893a73c
|
@ -270,14 +270,14 @@ int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||||
uip_ipaddr_t ipaddr;
|
uip_ipaddr_t ipaddr;
|
||||||
uint32 start;
|
uint32 start;
|
||||||
uint32 next;
|
uint32 next;
|
||||||
uint32 dsec;
|
uint32 dsec = 10;
|
||||||
uint16 id;
|
uint16 id;
|
||||||
int sec = 1;
|
|
||||||
int count = 10;
|
int count = 10;
|
||||||
int option;
|
int option;
|
||||||
int seqno;
|
int seqno;
|
||||||
int replies = 0;
|
int replies = 0;
|
||||||
int elapsed;
|
int elapsed;
|
||||||
|
int tmp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Get the ping options */
|
/* Get the ping options */
|
||||||
|
@ -296,12 +296,13 @@ int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
sec = atoi(optarg);
|
tmp = atoi(optarg);
|
||||||
if (sec < 1 || sec >= 4294)
|
if (tmp < 1 || tmp >= 4294)
|
||||||
{
|
{
|
||||||
fmt = g_fmtargrange;
|
fmt = g_fmtargrange;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
dsec = 10 * tmp;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ':':
|
case ':':
|
||||||
|
@ -334,39 +335,67 @@ int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the ping interval to microseconds and deciseconds*/
|
|
||||||
|
|
||||||
dsec = 10 * sec;
|
|
||||||
|
|
||||||
/* Get the ID to use */
|
/* Get the ID to use */
|
||||||
|
|
||||||
id = ping_newid();
|
id = ping_newid();
|
||||||
|
|
||||||
/* Loop for the specified count */
|
/* Loop for the specified count */
|
||||||
|
|
||||||
nsh_output(vtbl, "PING %s %dbytes of data\n", staddr, DEFAULT_PING_DATALEN);
|
nsh_output(vtbl, "PING %s %d bytes of data\n", staddr, DEFAULT_PING_DATALEN);
|
||||||
start = g_system_timer;
|
start = g_system_timer;
|
||||||
for (i = 0; i < count; i++)
|
for (i = 1; i <= count; i++)
|
||||||
{
|
{
|
||||||
next = g_system_timer;
|
/* Send the ECHO request and wait for the response */
|
||||||
|
|
||||||
|
next = g_system_timer;
|
||||||
seqno = uip_ping(ipaddr, id, i, DEFAULT_PING_DATALEN, dsec);
|
seqno = uip_ping(ipaddr, id, i, DEFAULT_PING_DATALEN, dsec);
|
||||||
elapsed = TICK2MSEC(g_system_timer - next);
|
|
||||||
if (seqno >= 0)
|
/* Was any response returned? We can tell if a non-negative sequence
|
||||||
|
* number was returned.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (seqno >= 0 && seqno <= i)
|
||||||
{
|
{
|
||||||
|
/* Get the elpased time from the time that the request was
|
||||||
|
* sent until the response was received. If we got a response
|
||||||
|
* to an earlier request, then fudge the elpased time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
elapsed = TICK2MSEC(g_system_timer - next);
|
||||||
|
if (seqno < i)
|
||||||
|
{
|
||||||
|
elapsed += 100*dsec*(i - seqno);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Report the receipt of the reply */
|
||||||
|
|
||||||
nsh_output(vtbl, "%d bytes from %s: icmp_seq=%d time=%d ms\n",
|
nsh_output(vtbl, "%d bytes from %s: icmp_seq=%d time=%d ms\n",
|
||||||
DEFAULT_PING_DATALEN, staddr, seqno, elapsed);
|
DEFAULT_PING_DATALEN, staddr, seqno, elapsed);
|
||||||
replies++;
|
replies++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wait for the remainder of the interval. If the last seqno<i,
|
||||||
|
* then this is a bad idea... we will probably lose the response
|
||||||
|
* to the current request!
|
||||||
|
*/
|
||||||
|
|
||||||
elapsed = TICK2DSEC(g_system_timer - next);
|
elapsed = TICK2DSEC(g_system_timer - next);
|
||||||
if (elapsed < dsec)
|
if (elapsed < dsec)
|
||||||
{
|
{
|
||||||
usleep(100000*dsec);
|
usleep(100000*dsec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the total elapsed time */
|
||||||
|
|
||||||
elapsed = TICK2MSEC(g_system_timer - start);
|
elapsed = TICK2MSEC(g_system_timer - start);
|
||||||
|
|
||||||
nsh_output(vtbl, "%d packets transmitted, %d received, %d%% packet loss, time %dms\n",
|
/* Calculate the percentage of lost packets */
|
||||||
count, replies, (100*replies + count/2)/count, elapsed);
|
|
||||||
|
tmp = (100*(count - replies) + (count >> 1)) / count;
|
||||||
|
|
||||||
|
nsh_output(vtbl, "%d packets transmitted, %d received, %d%% packet loss, time %d ms\n",
|
||||||
|
count, replies, tmp, elapsed);
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
|
|
|
@ -91,7 +91,13 @@
|
||||||
#define UIP_TS_MASK 15
|
#define UIP_TS_MASK 15
|
||||||
#define UIP_STOPPED 16
|
#define UIP_STOPPED 16
|
||||||
|
|
||||||
/* Header sizes */
|
/* Flag bits in 16-bit flags+ipoffset IPv4 TCP header field */
|
||||||
|
|
||||||
|
#define UIP_TCPFLAG_RESERVED 0x8000
|
||||||
|
#define UIP_TCPFLAG_DONTFRAG 0x4000
|
||||||
|
#define UIP_TCPFLAG_MOREFRAGS 0x2000
|
||||||
|
|
||||||
|
/* TCP header sizes */
|
||||||
|
|
||||||
#define UIP_TCPH_LEN 20 /* Size of TCP header */
|
#define UIP_TCPH_LEN 20 /* Size of TCP header */
|
||||||
#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + TCP header */
|
#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + TCP header */
|
||||||
|
|
|
@ -174,13 +174,13 @@ EXTERN FAR struct uip_driver_s *netdev_findbyname(const char *ifname);
|
||||||
/* net-findbyaddr.c **********************************************************/
|
/* net-findbyaddr.c **********************************************************/
|
||||||
|
|
||||||
#if CONFIG_NSOCKET_DESCRIPTORS > 0
|
#if CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||||
EXTERN FAR struct uip_driver_s *netdev_findbyaddr(uip_ipaddr_t *raddr);
|
EXTERN FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t *raddr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* net-txnotify.c ************************************************************/
|
/* net-txnotify.c ************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NSOCKET_DESCRIPTORS > 0
|
#if CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||||
EXTERN void netdev_txnotify(uip_ipaddr_t *raddr);
|
EXTERN void netdev_txnotify(const uip_ipaddr_t *raddr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* net-count.c ***************************************************************/
|
/* net-count.c ***************************************************************/
|
||||||
|
|
|
@ -105,7 +105,7 @@ static inline boolean netdev_maskcmp(uip_ipaddr_t *ipaddr, uip_ipaddr_t *raddr,
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct uip_driver_s *netdev_findbyaddr(uip_ipaddr_t *raddr)
|
FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t *raddr)
|
||||||
{
|
{
|
||||||
struct uip_driver_s *dev;
|
struct uip_driver_s *dev;
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void netdev_txnotify(uip_ipaddr_t *raddr)
|
void netdev_txnotify(const uip_ipaddr_t *raddr)
|
||||||
{
|
{
|
||||||
/* Find the device driver that serves the subnet of the remote address */
|
/* Find the device driver that serves the subnet of the remote address */
|
||||||
|
|
||||||
|
|
|
@ -323,10 +323,7 @@ void uip_arp_arpin(struct uip_driver_s *dev)
|
||||||
|
|
||||||
uip_arp_update(ARPBUF->ah_sipaddr, ARPBUF->ah_shwaddr);
|
uip_arp_update(ARPBUF->ah_sipaddr, ARPBUF->ah_shwaddr);
|
||||||
|
|
||||||
/* The reply opcode is 2. */
|
ARPBUF->ah_opcode = HTONS(ARP_REPLY);
|
||||||
|
|
||||||
ARPBUF->ah_opcode = HTONS(2);
|
|
||||||
|
|
||||||
memcpy(ARPBUF->ah_dhwaddr, ARPBUF->ah_shwaddr, ETHER_ADDR_LEN);
|
memcpy(ARPBUF->ah_dhwaddr, ARPBUF->ah_shwaddr, ETHER_ADDR_LEN);
|
||||||
memcpy(ARPBUF->ah_shwaddr, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN);
|
memcpy(ARPBUF->ah_shwaddr, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN);
|
||||||
memcpy(ETHBUF->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN);
|
memcpy(ETHBUF->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN);
|
||||||
|
|
|
@ -236,7 +236,7 @@ uint16 uip_callbackexecute(FAR struct uip_driver_s *dev, void *pvconn, uint16 fl
|
||||||
* beginning of the list (which will be ignored on this pass)
|
* beginning of the list (which will be ignored on this pass)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
vdbg("Call event=%p with flags=%04x\n", list->event, flags);
|
nvdbg("Call event=%p with flags=%04x\n", list->event, flags);
|
||||||
flags = list->event(dev, pvconn, list->private, flags);
|
flags = list->event(dev, pvconn, list->private, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/uip/uip-chksum.c
|
* net/uip/uip-chksum.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
|
|
@ -243,7 +243,23 @@ typeerr:
|
||||||
#ifdef CONFIG_NET_ICMP_PING
|
#ifdef CONFIG_NET_ICMP_PING
|
||||||
else if (ICMPBUF->type == ICMP6_ECHO_REPLY && g_echocallback)
|
else if (ICMPBUF->type == ICMP6_ECHO_REPLY && g_echocallback)
|
||||||
{
|
{
|
||||||
(void)uip_callbackexecute(dev, ICMPBUF, UIP_ECHOREPLY, g_echocallback);
|
uint16 flags = UIP_ECHOREPLY;
|
||||||
|
|
||||||
|
if (g_echocallback)
|
||||||
|
{
|
||||||
|
/* Dispatch the ECHO reply to the waiting thread */
|
||||||
|
|
||||||
|
flags = uip_callbackexecute(dev, ICMPBUF, flags, g_echocallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the ECHO reply was not handled, then drop the packet */
|
||||||
|
|
||||||
|
if (flags == UIP_ECHOREPLY)
|
||||||
|
{
|
||||||
|
/* The ECHO reply was not handled */
|
||||||
|
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define ICMPBUF ((struct uip_icmpip_hdr *)&dev->d_buf[UIP_LLH_LEN])
|
#define ICMPBUF ((struct uip_icmpip_hdr *)&dev->d_buf[UIP_LLH_LEN])
|
||||||
#define ICMPDAT &dev->d_buf[UIP_LLH_LEN + sizeof(struct uip_icmpip_hdr)]
|
#define ICMPDAT (&dev->d_buf[UIP_LLH_LEN + sizeof(struct uip_icmpip_hdr)])
|
||||||
|
|
||||||
/* Allocate a new ICMP data callback */
|
/* Allocate a new ICMP data callback */
|
||||||
|
|
||||||
|
@ -149,6 +149,7 @@ static uint16 ping_interrupt(struct uip_driver_s *dev, void *conn,
|
||||||
{
|
{
|
||||||
struct icmp_ping_s *pstate = (struct icmp_ping_s *)pvprivate;
|
struct icmp_ping_s *pstate = (struct icmp_ping_s *)pvprivate;
|
||||||
int failcode = -ETIMEDOUT;
|
int failcode = -ETIMEDOUT;
|
||||||
|
int i;
|
||||||
|
|
||||||
nvdbg("flags: %04x\n", flags);
|
nvdbg("flags: %04x\n", flags);
|
||||||
if (pstate)
|
if (pstate)
|
||||||
|
@ -162,6 +163,7 @@ static uint16 ping_interrupt(struct uip_driver_s *dev, void *conn,
|
||||||
* that the destination address is not reachable.
|
* that the destination address is not reachable.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
nvdbg("Not reachable\n");
|
||||||
failcode = -ENETUNREACH;
|
failcode = -ENETUNREACH;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -175,8 +177,17 @@ static uint16 ping_interrupt(struct uip_driver_s *dev, void *conn,
|
||||||
if ((flags & UIP_ECHOREPLY) != 0 && conn != NULL)
|
if ((flags & UIP_ECHOREPLY) != 0 && conn != NULL)
|
||||||
{
|
{
|
||||||
struct uip_icmpip_hdr *icmp = (struct uip_icmpip_hdr *)conn;
|
struct uip_icmpip_hdr *icmp = (struct uip_icmpip_hdr *)conn;
|
||||||
|
ndbg("ECHO reply: id=%d seqno=%d\n", ntohs(icmp->id), ntohs(icmp->seqno));
|
||||||
|
|
||||||
if (ntohs(icmp->id) == pstate->png_id)
|
if (ntohs(icmp->id) == pstate->png_id)
|
||||||
{
|
{
|
||||||
|
/* Consume the ECHOREPLY */
|
||||||
|
|
||||||
|
flags &= ~UIP_ECHOREPLY;
|
||||||
|
dev->d_len = 0;
|
||||||
|
|
||||||
|
/* Return the result to the caller */
|
||||||
|
|
||||||
pstate->png_result = OK;
|
pstate->png_result = OK;
|
||||||
pstate->png_seqno = ntohs(icmp->seqno);
|
pstate->png_seqno = ntohs(icmp->seqno);
|
||||||
goto end_wait;
|
goto end_wait;
|
||||||
|
@ -213,13 +224,19 @@ static uint16 ping_interrupt(struct uip_driver_s *dev, void *conn,
|
||||||
#else
|
#else
|
||||||
# error "IPv6 ECHO Request not implemented"
|
# error "IPv6 ECHO Request not implemented"
|
||||||
#endif
|
#endif
|
||||||
memset(ICMPDAT, 0, pstate->png_datlen);
|
/* Add some easily verifiable data */
|
||||||
|
|
||||||
|
for (i = 0; i < pstate->png_datlen; i++)
|
||||||
|
{
|
||||||
|
ICMPDAT[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send the ICMP echo request. Note that d_sndlen is set to
|
/* Send the ICMP echo request. Note that d_sndlen is set to
|
||||||
* the size of the ICMP payload and does not include the size
|
* the size of the ICMP payload and does not include the size
|
||||||
* of the ICMP header.
|
* of the ICMP header.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
ndbg("Send ECHO request: seqno=%d\n", pstate->png_seqno);
|
||||||
dev->d_sndlen= pstate->png_datlen + 4;
|
dev->d_sndlen= pstate->png_datlen + 4;
|
||||||
uip_icmpsend(dev, &pstate->png_addr);
|
uip_icmpsend(dev, &pstate->png_addr);
|
||||||
pstate->png_sent = TRUE;
|
pstate->png_sent = TRUE;
|
||||||
|
@ -233,7 +250,7 @@ static uint16 ping_interrupt(struct uip_driver_s *dev, void *conn,
|
||||||
{
|
{
|
||||||
/* Yes.. report the timeout */
|
/* Yes.. report the timeout */
|
||||||
|
|
||||||
nvdbg("Ping timeout\n");
|
ndbg("Ping timeout\n");
|
||||||
pstate->png_result = failcode;
|
pstate->png_result = failcode;
|
||||||
goto end_wait;
|
goto end_wait;
|
||||||
}
|
}
|
||||||
|
@ -243,6 +260,8 @@ static uint16 ping_interrupt(struct uip_driver_s *dev, void *conn,
|
||||||
return flags;
|
return flags;
|
||||||
|
|
||||||
end_wait:
|
end_wait:
|
||||||
|
nvdbg("Resuming\n");
|
||||||
|
|
||||||
/* Do not allow any further callbacks */
|
/* Do not allow any further callbacks */
|
||||||
|
|
||||||
pstate->png_cb->flags = 0;
|
pstate->png_cb->flags = 0;
|
||||||
|
@ -313,6 +332,11 @@ int uip_ping(uip_ipaddr_t addr, uint16 id, uint16 seqno, uint16 datalen, int dse
|
||||||
state.png_cb->flags = UIP_POLL|UIP_ECHOREPLY;
|
state.png_cb->flags = UIP_POLL|UIP_ECHOREPLY;
|
||||||
state.png_cb->private = (void*)&state;
|
state.png_cb->private = (void*)&state;
|
||||||
state.png_cb->event = ping_interrupt;
|
state.png_cb->event = ping_interrupt;
|
||||||
|
state.png_result = -EINTR; /* Assume sem-wait interrupted by signal */
|
||||||
|
|
||||||
|
/* Notify the device driver of the availaibilty of TX data */
|
||||||
|
|
||||||
|
netdev_txnotify(&state.png_addr);
|
||||||
|
|
||||||
/* Wait for either the full round trip transfer to complete or
|
/* Wait for either the full round trip transfer to complete or
|
||||||
* for timeout to occur. (1) sem_wait will also terminate if a
|
* for timeout to occur. (1) sem_wait will also terminate if a
|
||||||
|
@ -321,7 +345,7 @@ int uip_ping(uip_ipaddr_t addr, uint16 id, uint16 seqno, uint16 datalen, int dse
|
||||||
* re-enabled when the task restarts.
|
* re-enabled when the task restarts.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
state.png_result = -EINTR; /* Assume sem-waited interrupt by signal */
|
ndbg("Start time: 0x%08x seqno: %d\n", state.png_time, seqno);
|
||||||
sem_wait(&state.png_sem);
|
sem_wait(&state.png_sem);
|
||||||
|
|
||||||
uip_icmpcallbackfree(state.png_cb);
|
uip_icmpcallbackfree(state.png_cb);
|
||||||
|
@ -334,10 +358,12 @@ int uip_ping(uip_ipaddr_t addr, uint16 id, uint16 seqno, uint16 datalen, int dse
|
||||||
|
|
||||||
if (!state.png_result)
|
if (!state.png_result)
|
||||||
{
|
{
|
||||||
|
ndbg("Return seqno=%d\n", state.png_seqno);
|
||||||
return (int)state.png_seqno;
|
return (int)state.png_seqno;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ndbg("Return error=%d\n", -state.png_result);
|
||||||
return state.png_result;
|
return state.png_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue