Skip to content

Commit 812b999

Browse files
benpiccojukkar
authored andcommitted
net: shell: Improve the output of the ping function
Report rtt, ttl and rssi if available. Signed-off-by: Benjamin Valentin <[email protected]>
1 parent 7c09695 commit 812b999

File tree

2 files changed

+178
-39
lines changed

2 files changed

+178
-39
lines changed

doc/reference/networking/net_shell.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ The following net-shell commands are implemented:
3131
print more information if :option:`CONFIG_NET_BUF_POOL_USAGE` is set."
3232
"net nbr", "Print neighbor information. Only available if
3333
:option:`CONFIG_NET_IPV6` is set."
34-
"net ping", "Ping a network host."
34+
"net ping [-c count] [-i interval ms]", "Ping a network host."
3535
"net route", "Show IPv6 network routes. Only available if
3636
:option:`CONFIG_NET_ROUTE` is set."
3737
"net stats", "Show network statistics."

subsys/net/ip/net_shell.c

Lines changed: 177 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2659,24 +2659,60 @@ static enum net_verdict handle_ipv6_echo_reply(struct net_pkt *pkt,
26592659
struct net_ipv6_hdr *ip_hdr,
26602660
struct net_icmp_hdr *icmp_hdr)
26612661
{
2662-
ARG_UNUSED(icmp_hdr);
2662+
NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access,
2663+
struct net_icmpv6_echo_req);
2664+
u32_t cycles;
2665+
struct net_icmpv6_echo_req *icmp_echo;
26632666

2664-
PR_SHELL(shell_for_ping, "Received echo reply from %s to %s\n",
2667+
icmp_echo = (struct net_icmpv6_echo_req *)net_pkt_get_data(pkt, &icmp_access);
2668+
if (icmp_echo == NULL) {
2669+
return -NET_DROP;
2670+
}
2671+
2672+
net_pkt_skip(pkt, sizeof(*icmp_echo));
2673+
if (net_pkt_read_be32(pkt, &cycles)) {
2674+
return -NET_DROP;
2675+
}
2676+
2677+
cycles = k_cycle_get_32() - cycles;
2678+
2679+
PR_SHELL(shell_for_ping, "%d bytes from %s to %s: icmp_seq=%d ttl=%d "
2680+
#ifdef CONFIG_IEEE802154
2681+
"rssi=%d "
2682+
#endif
2683+
#ifdef CONFIG_FLOAT
2684+
"time=%.2f ms\n",
2685+
#else
2686+
"time=%d ms\n",
2687+
#endif
2688+
ntohs(ip_hdr->len) - net_pkt_ipv6_ext_len(pkt) - NET_ICMPH_LEN,
26652689
net_sprint_ipv6_addr(&ip_hdr->src),
2666-
net_sprint_ipv6_addr(&ip_hdr->dst));
2690+
net_sprint_ipv6_addr(&ip_hdr->dst),
2691+
ntohs(icmp_echo->sequence),
2692+
ip_hdr->hop_limit,
2693+
#ifdef CONFIG_IEEE802154
2694+
net_pkt_ieee802154_rssi(pkt),
2695+
#endif
2696+
#ifdef CONFIG_FLOAT
2697+
(SYS_CLOCK_HW_CYCLES_TO_NS(cycles) / 1000000.f));
2698+
#else
2699+
(SYS_CLOCK_HW_CYCLES_TO_NS(cycles) / 1000000));
2700+
#endif
26672701
k_sem_give(&ping_timeout);
2668-
remove_ipv6_ping_handler();
26692702

26702703
net_pkt_unref(pkt);
26712704
return NET_OK;
26722705
}
26732706

2674-
static int ping_ipv6(const struct shell *shell, char *host)
2707+
static int ping_ipv6(const struct shell *shell,
2708+
char *host,
2709+
unsigned int count,
2710+
unsigned int interval)
26752711
{
26762712
struct in6_addr ipv6_target;
26772713
struct net_if *iface = net_if_get_default();
26782714
struct net_nbr *nbr;
2679-
int ret;
2715+
int ret = 0;
26802716

26812717
#if defined(CONFIG_NET_ROUTE)
26822718
struct net_route_entry *route;
@@ -2700,18 +2736,26 @@ static int ping_ipv6(const struct shell *shell, char *host)
27002736
}
27012737
#endif
27022738

2703-
ret = net_icmpv6_send_echo_request(iface,
2704-
&ipv6_target,
2705-
sys_rand32_get(),
2706-
sys_rand32_get(),
2707-
NULL,
2708-
0);
2709-
if (ret) {
2710-
remove_ipv6_ping_handler();
2711-
} else {
2712-
PR("Sent a ping to %s\n", host);
2739+
PR("PING %s\n", host);
2740+
2741+
for (int i = 0; i < count; ++i) {
2742+
u32_t time_stamp = htonl(k_cycle_get_32());
2743+
2744+
ret = net_icmpv6_send_echo_request(iface,
2745+
&ipv6_target,
2746+
sys_rand32_get(),
2747+
i,
2748+
&time_stamp,
2749+
sizeof(time_stamp));
2750+
if (ret) {
2751+
break;
2752+
}
2753+
2754+
k_sleep(interval);
27132755
}
27142756

2757+
remove_ipv6_ping_handler();
2758+
27152759
return ret;
27162760
}
27172761
#else
@@ -2740,46 +2784,111 @@ static enum net_verdict handle_ipv4_echo_reply(struct net_pkt *pkt,
27402784
struct net_ipv4_hdr *ip_hdr,
27412785
struct net_icmp_hdr *icmp_hdr)
27422786
{
2743-
PR_SHELL(shell_for_ping, "Received echo reply from %s to %s\n",
2787+
NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access,
2788+
struct net_icmpv4_echo_req);
2789+
u32_t cycles;
2790+
struct net_icmpv4_echo_req *icmp_echo;
2791+
2792+
icmp_echo = (struct net_icmpv4_echo_req *)net_pkt_get_data(pkt, &icmp_access);
2793+
if (icmp_echo == NULL) {
2794+
return -NET_DROP;
2795+
}
2796+
2797+
net_pkt_skip(pkt, sizeof(*icmp_echo));
2798+
if (net_pkt_read_be32(pkt, &cycles)) {
2799+
return -NET_DROP;
2800+
}
2801+
2802+
cycles = k_cycle_get_32() - cycles;
2803+
2804+
PR_SHELL(shell_for_ping, "%d bytes from %s to %s: icmp_seq=%d ttl=%d "
2805+
#ifdef CONFIG_FLOAT
2806+
"time=%.2f ms\n",
2807+
#else
2808+
"time=%d ms\n",
2809+
#endif
2810+
ntohs(ip_hdr->len) - net_pkt_ipv6_ext_len(pkt) - NET_ICMPH_LEN,
27442811
net_sprint_ipv4_addr(&ip_hdr->src),
2745-
net_sprint_ipv4_addr(&ip_hdr->dst));
2812+
net_sprint_ipv4_addr(&ip_hdr->dst),
2813+
ntohs(icmp_echo->sequence),
2814+
ip_hdr->ttl,
2815+
#ifdef CONFIG_FLOAT
2816+
(SYS_CLOCK_HW_CYCLES_TO_NS(cycles) / 1000000.f));
2817+
#else
2818+
(SYS_CLOCK_HW_CYCLES_TO_NS(cycles) / 1000000));
2819+
#endif
27462820
k_sem_give(&ping_timeout);
2747-
remove_ipv4_ping_handler();
27482821

27492822
net_pkt_unref(pkt);
27502823
return NET_OK;
27512824
}
27522825

2753-
static int ping_ipv4(const struct shell *shell, char *host)
2826+
static int ping_ipv4(const struct shell *shell,
2827+
char *host,
2828+
unsigned int count,
2829+
unsigned int interval)
27542830
{
27552831
struct in_addr ipv4_target;
2756-
int ret;
2832+
int ret = 0;
27572833

27582834
if (net_addr_pton(AF_INET, host, &ipv4_target) < 0) {
27592835
return -EINVAL;
27602836
}
27612837

2838+
struct net_if *iface = net_if_ipv4_select_src_iface(&ipv4_target);
2839+
27622840
net_icmpv4_register_handler(&ping4_handler);
27632841

2764-
ret = net_icmpv4_send_echo_request(
2765-
net_if_ipv4_select_src_iface(&ipv4_target),
2766-
&ipv4_target,
2767-
sys_rand32_get(),
2768-
sys_rand32_get(),
2769-
NULL,
2770-
0);
2771-
if (ret) {
2772-
remove_ipv4_ping_handler();
2773-
} else {
2774-
PR("Sent a ping to %s\n", host);
2842+
PR("PING %s\n", host);
2843+
2844+
for (int i = 0; i < count; ++i) {
2845+
u32_t time_stamp = htonl(k_cycle_get_32());
2846+
2847+
ret = net_icmpv4_send_echo_request(iface,
2848+
&ipv4_target,
2849+
sys_rand32_get(),
2850+
i,
2851+
&time_stamp,
2852+
sizeof(time_stamp));
2853+
if (ret) {
2854+
break;
2855+
}
2856+
2857+
k_sleep(interval);
27752858
}
27762859

2860+
remove_ipv4_ping_handler();
2861+
27772862
return ret;
27782863
}
27792864
#else
27802865
#define ping_ipv4(...) -ENOTSUP
27812866
#define remove_ipv4_ping_handler()
27822867
#endif /* CONFIG_NET_IPV4 */
2868+
2869+
static int _parse_arg(size_t *i, size_t argc, char *argv[])
2870+
{
2871+
int res = -1;
2872+
const char *str = argv[*i] + 2;
2873+
char *endptr;
2874+
2875+
if (*str == 0) {
2876+
if (*i + 1 >= argc) {
2877+
return -1;
2878+
}
2879+
2880+
*i += 1;
2881+
str = argv[*i];
2882+
}
2883+
2884+
res = strtol(str, &endptr, 10);
2885+
2886+
if (errno || (endptr == str)) {
2887+
return -1;
2888+
}
2889+
2890+
return res;
2891+
}
27832892
#endif /* CONFIG_NET_IPV6 || CONFIG_NET_IPV4 */
27842893

27852894
static int cmd_net_ping(const struct shell *shell, size_t argc, char *argv[])
@@ -2791,12 +2900,42 @@ static int cmd_net_ping(const struct shell *shell, size_t argc, char *argv[])
27912900

27922901
return -EOPNOTSUPP;
27932902
#else
2794-
char *host;
2903+
char *host = NULL;
27952904
int ret;
27962905

2797-
ARG_UNUSED(argc);
2906+
int count = 3;
2907+
int interval = 1000;
2908+
2909+
for (size_t i = 1; i < argc; ++i) {
2910+
2911+
if (*argv[i] != '-') {
2912+
host = argv[i];
2913+
continue;
2914+
}
27982915

2799-
host = argv[1];
2916+
switch (argv[i][1]) {
2917+
case 'c':
2918+
count = _parse_arg(&i, argc, argv);
2919+
if (count < 0) {
2920+
PR_WARNING("Parse error: %s\n", argv[i]);
2921+
return -ENOEXEC;
2922+
}
2923+
2924+
2925+
break;
2926+
case 'i':
2927+
interval = _parse_arg(&i, argc, argv);
2928+
if (interval < 0) {
2929+
PR_WARNING("Parse error: %s\n", argv[i]);
2930+
return -ENOEXEC;
2931+
}
2932+
2933+
break;
2934+
default:
2935+
PR_WARNING("Unrecognized argument: %s\n", argv[i]);
2936+
return -ENOEXEC;
2937+
}
2938+
}
28002939

28012940
if (!host) {
28022941
PR_WARNING("Target host missing\n");
@@ -2806,7 +2945,7 @@ static int cmd_net_ping(const struct shell *shell, size_t argc, char *argv[])
28062945
shell_for_ping = shell;
28072946

28082947
if (IS_ENABLED(CONFIG_NET_IPV6)) {
2809-
ret = ping_ipv6(shell, host);
2948+
ret = ping_ipv6(shell, host, count, interval);
28102949
if (!ret) {
28112950
goto wait_reply;
28122951
} else if (ret == -EIO) {
@@ -2816,7 +2955,7 @@ static int cmd_net_ping(const struct shell *shell, size_t argc, char *argv[])
28162955
}
28172956

28182957
if (IS_ENABLED(CONFIG_NET_IPV4)) {
2819-
ret = ping_ipv4(shell, host);
2958+
ret = ping_ipv4(shell, host, count, interval);
28202959
if (ret) {
28212960
if (ret == -EIO) {
28222961
PR_WARNING("Cannot send IPv4 ping\n");
@@ -3789,7 +3928,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(net_commands,
37893928
cmd_net_mem),
37903929
SHELL_CMD(nbr, &net_cmd_nbr, "Print neighbor information.",
37913930
cmd_net_nbr),
3792-
SHELL_CMD(ping, NULL, "Ping a network host.", cmd_net_ping),
3931+
SHELL_CMD(ping, NULL, "'net ping [-c count] [-i interval ms] <host>' ping a network host.", cmd_net_ping),
37933932
SHELL_CMD(route, NULL, "Show network route.", cmd_net_route),
37943933
SHELL_CMD(stacks, NULL, "Show network stacks information.",
37953934
cmd_net_stacks),

0 commit comments

Comments
 (0)