net/shell: Add ping reply handlers and a timeout

Thus the ping command is more user-friendly: at least user knows the
ping got a reply or not.

Change-Id: I740a2f77d288f6287ac04c908f3d517a49df57d2
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2017-03-24 09:18:03 +01:00 committed by Jukka Rissanen
commit e98f2e0b6a

View file

@ -783,41 +783,128 @@ static int shell_cmd_nbr(int argc, char *argv[])
return 0;
}
#if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_IPV4)
K_SEM_DEFINE(ping_timeout, 0, 1);
#if defined(CONFIG_NET_IPV6)
static enum net_verdict _handle_ipv6_echo_reply(struct net_buf *buf);
static struct net_icmpv6_handler ping6_handler = {
.type = NET_ICMPV6_ECHO_REPLY,
.code = 0,
.handler = _handle_ipv6_echo_reply,
};
static inline void _remove_ipv6_ping_handler(void)
{
net_icmpv6_unregister_handler(&ping6_handler);
}
static enum net_verdict _handle_ipv6_echo_reply(struct net_buf *buf)
{
char addr[NET_IPV6_ADDR_LEN];
snprintk(addr, sizeof(addr), "%s",
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->dst));
printk("Received echo reply from %s to %s\n",
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->src), addr);
k_sem_give(&ping_timeout);
_remove_ipv6_ping_handler();
return NET_OK;
}
static int _ping_ipv6(char *host)
{
struct in6_addr ipv6_target;
int ret;
if (net_addr_pton(AF_INET6, host, &ipv6_target) < 0) {
return -EINVAL;
}
return net_icmpv6_send_echo_request(net_if_get_default(),
net_icmpv6_register_handler(&ping6_handler);
ret = net_icmpv6_send_echo_request(net_if_get_default(),
&ipv6_target,
sys_rand32_get(),
sys_rand32_get());
if (ret) {
_remove_ipv6_ping_handler();
} else {
printk("Sent a ping to %s\n", host);
}
return ret;
}
#else
#define _ping_ipv6(...) -EINVAL
#define _remove_ipv6_ping_handler()
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
static enum net_verdict _handle_ipv4_echo_reply(struct net_buf *buf);
static struct net_icmpv4_handler ping4_handler = {
.type = NET_ICMPV4_ECHO_REPLY,
.code = 0,
.handler = _handle_ipv4_echo_reply,
};
static inline void _remove_ipv4_ping_handler(void)
{
net_icmpv4_unregister_handler(&ping4_handler);
}
static enum net_verdict _handle_ipv4_echo_reply(struct net_buf *buf)
{
char addr[NET_IPV4_ADDR_LEN];
snprintk(addr, sizeof(addr), "%s",
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->dst));
printk("Received echo reply from %s to %s\n",
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->src), addr);
k_sem_give(&ping_timeout);
_remove_ipv4_ping_handler();
return NET_OK;
}
static int _ping_ipv4(char *host)
{
struct in_addr ipv4_target;
int ret;
if (net_addr_pton(AF_INET, host, &ipv4_target) < 0) {
return -EINVAL;
}
return net_icmpv4_send_echo_request(net_if_get_default(),
net_icmpv4_register_handler(&ping4_handler);
ret = net_icmpv4_send_echo_request(net_if_get_default(),
&ipv4_target,
sys_rand32_get(),
sys_rand32_get());
if (ret) {
_remove_ipv4_ping_handler();
} else {
printk("Sent a ping to %s\n", host);
}
return ret;
}
#else
#define _ping_ipv4(...) -EINVAL
#define _remove_ipv4_ping_handler()
#endif /* CONFIG_NET_IPV4 */
#endif /* CONFIG_NET_IPV6 || CONFIG_NET_IPV4 */
static int shell_cmd_ping(int argc, char *argv[])
{
@ -834,19 +921,29 @@ static int shell_cmd_ping(int argc, char *argv[])
ret = _ping_ipv6(host);
if (!ret) {
return 0;
goto wait_reply;
} else if (ret == -EIO) {
printk("Cannot send IPv6 ping\n");
return 0;
}
ret = _ping_ipv4(host);
if (ret) {
if (ret == -EIO) {
printk("Cannot send IPv4 ping\n");
} else if (ret == -EINVAL) {
printk("Invalid IP address\n");
}
if (ret == -EINVAL) {
printk("Invalid IP address\n");
return 0;
}
wait_reply:
ret = k_sem_take(&ping_timeout, K_SECONDS(2));
if (ret == -EAGAIN) {
printk("Ping timeout\n");
_remove_ipv6_ping_handler();
_remove_ipv4_ping_handler();
}
return 0;