From 2d73d127546981ee8d4cf7eca38b3f057feb459b Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sat, 7 Jul 2018 14:54:31 +0200 Subject: [PATCH] shell_commands: adapt ping6 to original-ping-like implementation Loosely based on [the original ping] and [netutil]'s ping New features (compared to old RIOT version): - non-positional parameters - Better duplicate detection (addresses #9387) - Better asynchronous behavior - Potential for future move to `sock_ip` - (Optional) DNS-support - Multithreading-safe (in case shell-command handler gets called from multiple threads) [the original ping]: http://ftp.arl.army.mil/~mike/ping.html [netutil]: https://www.gnu.org/software/inetutils/ --- sys/shell/commands/Makefile | 2 +- sys/shell/commands/sc_gnrc_icmpv6_echo.c | 404 +++++++++++++++++++++++ sys/shell/commands/sc_icmpv6_echo.c | 347 ------------------- sys/shell/commands/shell_commands.c | 4 +- 4 files changed, 407 insertions(+), 350 deletions(-) create mode 100644 sys/shell/commands/sc_gnrc_icmpv6_echo.c delete mode 100644 sys/shell/commands/sc_icmpv6_echo.c diff --git a/sys/shell/commands/Makefile b/sys/shell/commands/Makefile index 5d1908f2d13e9..c038179e3c8c1 100644 --- a/sys/shell/commands/Makefile +++ b/sys/shell/commands/Makefile @@ -37,7 +37,7 @@ ifneq (,$(filter gnrc_ipv6_blacklist,$(USEMODULE))) endif ifneq (,$(filter gnrc_icmpv6_echo,$(USEMODULE))) ifneq (,$(filter xtimer,$(USEMODULE))) - SRC += sc_icmpv6_echo.c + SRC += sc_gnrc_icmpv6_echo.c endif endif ifneq (,$(filter gnrc_pktbuf_cmd,$(USEMODULE))) diff --git a/sys/shell/commands/sc_gnrc_icmpv6_echo.c b/sys/shell/commands/sc_gnrc_icmpv6_echo.c new file mode 100644 index 0000000000000..f92b6f11dbb48 --- /dev/null +++ b/sys/shell/commands/sc_gnrc_icmpv6_echo.c @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + * @author Martine Lenders + * + * This implementation oriented itself on the [version by Mike + * Muuss](http://ftp.arl.army.mil/~mike/ping.html) which was published under + * public domain. The state-handling and duplicate detection was inspired by the + * ping version of [inetutils](://www.gnu.org/software/inetutils/), which was + * published under GPLv3 + */ + +#ifdef MODULE_GNRC_ICMPV6 +#include +#include +#include + +#include "bitfield.h" +#include "byteorder.h" +#include "kernel_types.h" +#ifdef MODULE_LUID +#include "luid.h" +#endif +#include "msg.h" +#include "net/gnrc.h" +#include "net/gnrc/icmpv6.h" +#include "net/icmpv6.h" +#include "net/ipv6.h" +#include "timex.h" +#include "utlist.h" +#include "xtimer.h" + +#define _SEND_NEXT_PING (0xEF48) +#define _PING_FINISH (0xEF49) + +#define CKTAB_SIZE (64U * 8) /* 64 byte * 8 bit/byte */ + +#define DEFAULT_COUNT (3U) +#define DEFAULT_DATALEN (sizeof(uint32_t)) +#define DEFAULT_ID (0x53) +#define DEFAULT_INTERVAL_USEC (1U * US_PER_SEC) +#define DEFAULT_TIMEOUT_USEC (1U * US_PER_SEC) + +typedef struct { + gnrc_netreg_entry_t netreg; + xtimer_t sched_timer; + msg_t sched_msg; + ipv6_addr_t host; + char *hostname; + unsigned long num_sent, num_recv, num_rept; + unsigned long long tsum; + unsigned tmin, tmax; + unsigned count; + size_t datalen; + BITFIELD(cktab, CKTAB_SIZE); + uint32_t timeout; + uint32_t interval; + kernel_pid_t iface; + uint16_t id; + uint8_t hoplimit; + uint8_t pattern; +} _ping_data_t; + +static void _usage(char *cmdname); +static int _configure(int argc, char **argv, _ping_data_t *data); +static void _pinger(_ping_data_t *data); +static void _print_reply(_ping_data_t *data, gnrc_pktsnip_t *icmpv6, + ipv6_addr_t *from, int hoplimit); +static void _handle_reply(_ping_data_t *data, gnrc_pktsnip_t *pkt); +static int _finish(_ping_data_t *data); + +int _gnrc_icmpv6_ping(int argc, char **argv) +{ + _ping_data_t data = { + .netreg = GNRC_NETREG_ENTRY_INIT_PID(ICMPV6_ECHO_REP, + sched_active_pid), + .count = DEFAULT_COUNT, + .tmin = UINT_MAX, + .datalen = DEFAULT_DATALEN, + .timeout = DEFAULT_TIMEOUT_USEC, + .interval = DEFAULT_INTERVAL_USEC, + .id = DEFAULT_ID, + .pattern = DEFAULT_ID, + }; + int res; + + if ((res = _configure(argc, argv, &data)) != 0) { + return res; + } + gnrc_netreg_register(GNRC_NETTYPE_ICMPV6, &data.netreg); + _pinger(&data); + do { + msg_t msg; + + msg_receive(&msg); + switch (msg.type) { + case GNRC_NETAPI_MSG_TYPE_RCV: { + _handle_reply(&data, msg.content.ptr); + gnrc_pktbuf_release(msg.content.ptr); + break; + } + case _SEND_NEXT_PING: + _pinger(&data); + break; + case _PING_FINISH: + goto finish; + default: + /* requeue wrong packets */ + msg_send(&msg, sched_active_pid); + break; + } + } while (data.num_recv < data.count); +finish: + xtimer_remove(&data.sched_timer); + res = _finish(&data); + gnrc_netreg_unregister(GNRC_NETTYPE_ICMPV6, &data.netreg); + return res; +} + +static void _usage(char *cmdname) +{ + printf("%s [-c ] [-h] [-i ] [-s ]\n", + cmdname); + puts(" [-t hoplimit] [-W ] [%]"); + puts(" count: number of pings (default: 3)"); + puts(" ms interval: wait interval milliseconds between sending " + "(default: 1000)"); + puts(" packetsize: number of bytes in echo payload; must be >= 4 to " + "measure round trip time (default: 4)"); + puts(" hoplimit: Set the IP time to life/hoplimit " + "(default: interface config)"); + puts(" ms timeout: Time to wait for a resonse in milliseconds " + "(default: 1000). he option affects only timeout in absence " + "of any responses, otherwise wait for two RTTs"); +} + +static int _configure(int argc, char **argv, _ping_data_t *data) +{ + char *cmdname = argv[0]; + int res = 0; + + /* jump over cmdname */ + argc--; + argv++; + /* parse command line arguments */ + for (; argc > 0; argc--, argv++) { + if (argv[0][0] != '-') { + data->hostname = *argv; +#ifdef MODULE_SOCK_DNS + if (sock_dns_query(data->hostname, &data->host, AF_INET6) == 0) { + continue; + } +#endif + data->iface = ipv6_addr_split_iface(data->hostname); + if (data->iface < KERNEL_PID_UNDEF) { +#if GNRC_NETIF_NUMOF == 1 + gnrc_netif_t *netif = gnrc_netif_iter(NULL); + if (netif != NULL) { + data->iface = netif->pid; + } +#endif + } + if (ipv6_addr_from_str(&data->host, data->hostname) == NULL) { + res = 1; + break; + } + } + else { + switch (argv[0][1]) { + case 'c': + if (argc--) { + data->count = (unsigned)atoi(*(++argv)); + if (data->count > 0) { + continue; + } + } + /* falls through intentionally */ + case 'h': + res = 1; + continue; + /* falls through intentionally */ + case 'i': + if (argc--) { + data->interval = (uint32_t)atoi(*(++argv)) * US_PER_MS; + if (data->interval > 0) { + continue; + } + } + /* falls through intentionally */ + case 's': + if (argc--) { + data->datalen = atoi(*(++argv)); + continue; + } + /* falls through intentionally */ + case 't': + if (argc--) { + data->hoplimit = atoi(*(++argv)); + continue; + } + /* falls through intentionally */ + case 'W': + if (argc--) { + data->timeout = (uint32_t)atoi(*(++argv)) * US_PER_MS; + if (data->timeout > 0) { + continue; + } + } + /* falls through intentionally */ + default: + res = 1; + break; + } + } + } + if (res != 0) { + _usage(cmdname); + } +#ifdef MODULE_LUID + luid_custom(&data->id, sizeof(data->id), DEFAULT_ID); +#endif + return res; +} + +static void _pinger(_ping_data_t *data) +{ + gnrc_pktsnip_t *pkt, *tmp; + ipv6_hdr_t *ipv6; + uint32_t timer; + uint8_t *databuf; + + /* schedule next event (next ping or finish) ASAP */ + if ((data->num_sent + 1) < data->count) { + /* didn't send all pings yet - schedule next in data->interval */ + data->sched_msg.type = _SEND_NEXT_PING; + timer = data->interval; + } + else { + /* Wait for the last ping to come back. + * data->timeout: wait for a response in milliseconds. + * Affects only timeout in absence of any responses, + * otherwise ping waits for two max RTTs. */ + data->sched_msg.type = _PING_FINISH; + timer = data->timeout; + if (data->num_recv) { + /* approx. 2*tmax, in seconds (2 RTT) */ + timer = (data->tmax / (512 * 1024)) * US_PER_SEC; + if (timer == 0) { + timer = 1U * US_PER_SEC; + } + } + } + xtimer_set_msg(&data->sched_timer, timer, &data->sched_msg, + sched_active_pid); + bf_unset(data->cktab, (size_t)data->num_sent % CKTAB_SIZE); + pkt = gnrc_icmpv6_echo_build(ICMPV6_ECHO_REQ, data->id, + (uint16_t)data->num_sent++, + NULL, data->datalen); + if (pkt == NULL) { + puts("error: packet buffer full"); + return; + } + databuf = (uint8_t *)(pkt->data) + sizeof(icmpv6_echo_t); + memset(databuf, data->pattern, data->datalen); + tmp = gnrc_ipv6_hdr_build(pkt, NULL, &data->host); + if (tmp == NULL) { + puts("error: packet buffer full"); + goto error_exit; + } + pkt = tmp; + ipv6 = pkt->data; + /* if data->hoplimit is unset (i.e. 0) gnrc_ipv6 will select hop limit */ + ipv6->hl = data->hoplimit; + if (data->iface > KERNEL_PID_UNDEF) { + gnrc_netif_hdr_t *netif; + + tmp = gnrc_netif_hdr_build(NULL, 0, NULL, 0); + if (tmp == NULL) { + puts("error: packet buffer full"); + goto error_exit; + } + netif = tmp->data; + netif->if_pid = data->iface; + LL_PREPEND(pkt, tmp); + } + if (data->datalen >= sizeof(uint32_t)) { + *((uint32_t *)databuf) = xtimer_now_usec(); + } + if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, + GNRC_NETREG_DEMUX_CTX_ALL, + pkt)) { + puts("error: unable to send ICMPv6 echo request"); + goto error_exit; + } + return; +error_exit: + gnrc_pktbuf_release(pkt); +} + +static void _print_reply(_ping_data_t *data, gnrc_pktsnip_t *icmpv6, + ipv6_addr_t *from, int hoplimit) +{ + icmpv6_echo_t *icmpv6_hdr = icmpv6->data; + char from_str[IPV6_ADDR_MAX_STR_LEN]; + + /* discard if too short */ + if (icmpv6->size < (data->datalen + sizeof(icmpv6_echo_t))) { + return; + } + if (icmpv6_hdr->type == ICMPV6_ECHO_REP) { + const char *dupmsg = " (DUP!)"; + uint32_t triptime = 0; + uint16_t recv_seq; + + /* not our ping */ + if (byteorder_ntohs(icmpv6_hdr->id) != data->id) { + return; + } + recv_seq = byteorder_ntohs(icmpv6_hdr->seq); + ipv6_addr_to_str(&from_str[0], from, sizeof(from_str)); + if (data->datalen >= sizeof(uint32_t)) { + triptime = xtimer_now_usec() - *((uint32_t *)(icmpv6_hdr + 1)); + data->tsum += triptime; + if (triptime < data->tmin) { + data->tmin = triptime; + } + if (triptime > data->tmax) { + data->tmax = triptime; + } + } + if (bf_isset(data->cktab, recv_seq % CKTAB_SIZE)) { + data->num_rept++; + } + else { + bf_set(data->cktab, recv_seq % CKTAB_SIZE); + data->num_recv++; + dupmsg += 7; + } + printf("%u bytes from %s: icmp_seq=%u ttl=%u", (unsigned)icmpv6->size, + from_str, recv_seq, hoplimit); + if (data->datalen >= sizeof(uint32_t)) { + printf(" time=%u.%03u ms", triptime / 1000, triptime % 1000); + } + puts(dupmsg); + fflush(stdout); + } +} + +static void _handle_reply(_ping_data_t *data, gnrc_pktsnip_t *pkt) +{ + gnrc_pktsnip_t *ipv6, *icmpv6; + ipv6_hdr_t *ipv6_hdr; + + ipv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_IPV6); + icmpv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_ICMPV6); + if ((ipv6 == NULL) || (icmpv6 == NULL)) { + puts("No IPv6 or ICMPv6 header found in reply"); + return; + } + ipv6_hdr = ipv6->data; + _print_reply(data, icmpv6, &ipv6_hdr->src, ipv6_hdr->hl); +} + +static int _finish(_ping_data_t *data) +{ + unsigned long tmp, nrecv, ndup; + + tmp = data->num_sent; + nrecv = data->num_recv; + ndup = data->num_rept; + printf("\n--- %s PING statistics ---\n" + "%lu packets transmitted, " + "%lu packets received, ", + data->hostname, tmp, nrecv); + if (ndup) { + printf("%lu duplicates, ", ndup); + } + if (tmp > 0) { + tmp = ((tmp - nrecv) * 100) / tmp; + } + printf("%lu%% packet loss\n", tmp); + if (data->tmin != UINT_MAX) { + unsigned tavg = data->tsum / (nrecv + ndup); + printf("round-trip min/avg/max = %u.%03u/%u.%03u/%u.%03u ms\n", + data->tmin / 1000, data->tmin % 1000, + tavg / 1000, tavg % 1000, + data->tmax / 1000, data->tmax % 1000); + } + /* if condition is true, exit with 1 -- 'failure' */ + return (nrecv == 0); +} + +#endif /* MODULE_GNRC_ICMPV6 */ + +/** @} */ diff --git a/sys/shell/commands/sc_icmpv6_echo.c b/sys/shell/commands/sc_icmpv6_echo.c deleted file mode 100644 index a473de6d32f4c..0000000000000 --- a/sys/shell/commands/sc_icmpv6_echo.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (C) 2015 Martine Lenders - * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License v2.1. See the file LICENSE in the top level directory for - * more details. - */ - -/** - * @ingroup sys_shell_commands - * @{ - * - * @file - * - * @author Martine Lenders - */ - -#include -#include -#include - -#ifdef MODULE_GNRC_ICMPV6 - -#include "byteorder.h" -#include "net/gnrc/icmpv6.h" -#include "net/ipv6/addr.h" -#ifdef MODULE_GNRC_IPV6_NIB -#include "net/gnrc/ipv6/nib/nc.h" -#endif -#include "net/gnrc/ipv6/hdr.h" -#include "net/gnrc/netif.h" -#include "net/gnrc.h" -#include "thread.h" -#include "utlist.h" -#include "xtimer.h" - -static uint16_t id = 0x53; -static uint16_t min_seq_expected = 0; -static uint16_t max_seq_expected = 0; -static char ipv6_str[IPV6_ADDR_MAX_STR_LEN]; - -static void usage(char **argv) -{ - printf("%s [] [%%] [] [] []\n", argv[0]); - puts("defaults:"); - puts(" count = 3"); - puts(" interface = first interface if only one present, only needed for link-local addresses"); - puts(" payload_len = 4"); - puts(" delay = 1000"); - puts(" stats interval = count"); -} - -void _set_payload(icmpv6_echo_t *hdr, size_t payload_len) -{ - size_t i = 0; - uint8_t *payload = (uint8_t *)(hdr + 1); - - while (i < payload_len) { - if (id > 0xff) { - payload[i] = (uint8_t)(id >> 8); - payload[i + 1] = (uint8_t)(id & 0xff); - i += 2; - } - else { - payload[i++] = (uint8_t)(id & 0xff); - } - } - - if (i > payload_len) { /* when id > 0xff and payload_len is odd */ - payload[payload_len - 1] = id >> 8; - } -} - -static inline bool _expected_seq(uint16_t seq) -{ - /* take integer overflows in account */ - if (min_seq_expected > max_seq_expected) { - return (seq >= min_seq_expected) || (seq <= max_seq_expected); - } - else { - return (seq >= min_seq_expected) && (seq <= max_seq_expected); - } -} - -int _handle_reply(gnrc_pktsnip_t *pkt, uint32_t time) -{ - gnrc_pktsnip_t *ipv6, *icmpv6; - ipv6_hdr_t *ipv6_hdr; - icmpv6_echo_t *icmpv6_hdr; - uint16_t seq; - - ipv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_IPV6); - icmpv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_ICMPV6); - - if ((ipv6 == NULL) || (icmpv6 == NULL)) { - puts("error: IPv6 header or ICMPv6 header not found in reply"); - return 0; - } - - ipv6_hdr = ipv6->data; - icmpv6_hdr = icmpv6->data; - seq = byteorder_ntohs(icmpv6_hdr->seq); - - if ((byteorder_ntohs(icmpv6_hdr->id) == id) && _expected_seq(seq)) { - if (seq <= min_seq_expected) { - min_seq_expected++; - } - - printf("%u bytes from %s: id=%" PRIu16 " seq=%" PRIu16 " hop limit=%u time = %" - PRIu32 ".%03" PRIu32 " ms\n", (unsigned) icmpv6->size, - ipv6_addr_to_str(ipv6_str, &(ipv6_hdr->src), sizeof(ipv6_str)), - byteorder_ntohs(icmpv6_hdr->id), seq, (unsigned)ipv6_hdr->hl, - time / US_PER_MS, time % US_PER_MS); -#ifdef MODULE_GNRC_IPV6_NIB - gnrc_ipv6_nib_nc_mark_reachable(&ipv6_hdr->src); -#endif - } - else { - puts("error: unexpected parameters"); - return 0; - } - - return 1; -} - -static void _print_stats(char *addr_str, int success, int count, uint64_t total_time, - uint64_t sum_rtt, uint32_t min_rtt, uint32_t max_rtt) -{ - printf("--- %s ping statistics ---\n", addr_str); - - if (success > 0) { - uint32_t avg_rtt = (uint32_t)(sum_rtt / success); /* get average */ - printf("%d packets transmitted, %d received, %d%% packet loss, time %" - PRIu32 ".06%" PRIu32 " s\n", count, success, - (100 - ((success * 100) / count)), - (uint32_t)total_time / US_PER_SEC, (uint32_t)total_time % US_PER_SEC); - printf("rtt min/avg/max = " - "%" PRIu32 ".%03" PRIu32 "/" - "%" PRIu32 ".%03" PRIu32 "/" - "%" PRIu32 ".%03" PRIu32 " ms\n", - min_rtt / US_PER_MS, min_rtt % US_PER_MS, - avg_rtt / US_PER_MS, avg_rtt % US_PER_MS, - max_rtt / US_PER_MS, max_rtt % US_PER_MS); - } - else { - printf("%d packets transmitted, 0 received, 100%% packet loss\n", count); - } -} - -int _icmpv6_ping(int argc, char **argv) -{ - int count = 3, success = 0, remaining, stat_interval = 0, stat_counter = 0; - size_t payload_len = 4; - uint32_t delay = 1 * MS_PER_SEC; - char *addr_str; - ipv6_addr_t addr; - kernel_pid_t src_iface; - msg_t msg; - gnrc_netreg_entry_t my_entry = GNRC_NETREG_ENTRY_INIT_PID(ICMPV6_ECHO_REP, - sched_active_pid); - uint32_t min_rtt = UINT32_MAX, max_rtt = 0; - uint64_t sum_rtt = 0; - uint64_t ping_start; - int param_offset = 0; - - if (argc < 2) { - usage(argv); - return 1; - } - else if ((argc > 2) && ((count = atoi(argv[1])) > 0)) { - param_offset = 1; - } - else { - count = 3; - } - - stat_interval = count; - - addr_str = argv[1 + param_offset]; - if (argc > (2 + param_offset)) { - payload_len = atoi(argv[2 + param_offset]); - } - if (argc > (3 + param_offset)) { - delay = atoi(argv[3 + param_offset]); - } - if (argc > (4 + param_offset)) { - stat_interval = atoi(argv[4 + param_offset]); - } - - if ((int)payload_len < 0) { - usage(argv); - return 1; - } - - src_iface = ipv6_addr_split_iface(addr_str); - if (src_iface == -1) { - src_iface = KERNEL_PID_UNDEF; - } - - if (ipv6_addr_from_str(&addr, addr_str) == NULL) { - puts("error: malformed address"); - return 1; - } - - if (ipv6_addr_is_link_local(&addr) || (src_iface != KERNEL_PID_UNDEF)) { - size_t ifnum = gnrc_netif_numof(); - - if (src_iface == KERNEL_PID_UNDEF) { - if (ifnum == 1) { - src_iface = gnrc_netif_iter(NULL)->pid; - } - else { - puts("error: link local target needs interface parameter (use \"
%\")\n"); - return 1; - } - } - else { - if (gnrc_netif_get_by_pid(src_iface) == NULL) { - printf("error: %"PRIkernel_pid" is not a valid interface.\n", src_iface); - return 1; - } - } - } - - if (gnrc_netreg_register(GNRC_NETTYPE_ICMPV6, &my_entry) < 0) { - puts("error: network registry is full"); - return 1; - } - - remaining = count; - - ping_start = xtimer_now_usec64(); - - while ((remaining--) > 0) { - gnrc_pktsnip_t *pkt; - uint32_t start, timeout = 1 * US_PER_SEC; - - pkt = gnrc_icmpv6_echo_build(ICMPV6_ECHO_REQ, id, ++max_seq_expected, - NULL, payload_len); - - if (pkt == NULL) { - puts("error: packet buffer full"); - continue; - } - - _set_payload(pkt->data, payload_len); - - pkt = gnrc_ipv6_hdr_build(pkt, NULL, &addr); - - if (pkt == NULL) { - puts("error: packet buffer full"); - continue; - } - - if (src_iface != KERNEL_PID_UNDEF) { - pkt = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_netif_hdr_t), - GNRC_NETTYPE_NETIF); - - if (pkt == NULL) { - puts("error: packet buffer full"); - continue; - } - - gnrc_netif_hdr_init(((gnrc_netif_hdr_t *)pkt->data), 0, 0); - ((gnrc_netif_hdr_t *)pkt->data)->if_pid = src_iface; - } - - start = xtimer_now_usec(); - if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) { - puts("error: unable to send ICMPv6 echo request\n"); - gnrc_pktbuf_release(pkt); - continue; - } - - /* TODO: replace when #4219 was fixed */ - if (xtimer_msg_receive_timeout64(&msg, (uint64_t)timeout) >= 0) { - uint32_t stop; - switch (msg.type) { - case GNRC_NETAPI_MSG_TYPE_RCV: - stop = xtimer_now_usec() - start; - - gnrc_pktsnip_t *pkt = msg.content.ptr; - success += _handle_reply(pkt, stop); - gnrc_pktbuf_release(pkt); - - if (stop > max_rtt) { - max_rtt = stop; - } - - if (stop < min_rtt) { - min_rtt = stop; - } - - sum_rtt += stop; - - break; - - default: - /* requeue wrong packets */ - msg_send(&msg, thread_getpid()); - break; - } - } - else { - puts("ping timeout"); - } - - while (msg_try_receive(&msg) > 0) { - if (msg.type == GNRC_NETAPI_MSG_TYPE_RCV) { - printf("dropping additional response packet (probably caused by duplicates)\n"); - gnrc_pktsnip_t *pkt = msg.content.ptr; - gnrc_pktbuf_release(pkt); - } - } - - if (remaining > 0) { - xtimer_usleep64(delay * US_PER_MS); - } - if ((++stat_counter == stat_interval) || (remaining == 0)) { - uint64_t total_time = xtimer_now_usec64() - ping_start; - _print_stats(addr_str, success, (count - remaining), total_time, sum_rtt, min_rtt, - max_rtt); - stat_counter = 0; - } - - } - - max_seq_expected = 0; - id++; - - gnrc_netreg_unregister(GNRC_NETTYPE_ICMPV6, &my_entry); - while (msg_try_receive(&msg) > 0) { - if (msg.type == GNRC_NETAPI_MSG_TYPE_RCV) { - printf("dropping additional response packet (probably caused by duplicates)\n"); - gnrc_pktsnip_t *pkt = msg.content.ptr; - gnrc_pktbuf_release(pkt); - } - } - - return success ? 0 : 1; -} - -#endif - -/** - * @} - */ diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c index a9871517d3e64..2c6fb8a0a9e51 100644 --- a/sys/shell/commands/shell_commands.c +++ b/sys/shell/commands/shell_commands.c @@ -71,7 +71,7 @@ extern int _read_bytes(int argc, char **argv); #ifdef MODULE_GNRC_ICMPV6_ECHO #ifdef MODULE_XTIMER -extern int _icmpv6_ping(int argc, char **argv); +extern int _gnrc_icmpv6_ping(int argc, char **argv); #endif #endif @@ -175,7 +175,7 @@ const shell_command_t _shell_command_list[] = { #endif #ifdef MODULE_GNRC_ICMPV6_ECHO #ifdef MODULE_XTIMER - { "ping6", "Ping via ICMPv6", _icmpv6_ping }, + { "ping6", "Ping via ICMPv6", _gnrc_icmpv6_ping }, #endif #endif #ifdef MODULE_RANDOM