As the common.h is only meant to be used by the network shell files, rename it to be more descriptive in order to avoid possible conflicts with any other common.h file. Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
208 lines
4.6 KiB
C
208 lines
4.6 KiB
C
/*
|
|
* Copyright (c) 2016 Intel Corporation
|
|
* Copyright (c) 2023 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_DECLARE(net_shell);
|
|
|
|
#include "net_shell_private.h"
|
|
|
|
static int cmd_net_nbr_rm(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
#if defined(CONFIG_NET_IPV6)
|
|
struct in6_addr addr;
|
|
int ret;
|
|
#endif
|
|
|
|
#if defined(CONFIG_NET_IPV6)
|
|
if (!argv[1]) {
|
|
PR_WARNING("Neighbor IPv6 address missing.\n");
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
ret = net_addr_pton(AF_INET6, argv[1], &addr);
|
|
if (ret < 0) {
|
|
PR_WARNING("Cannot parse '%s'\n", argv[1]);
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
if (!net_ipv6_nbr_rm(NULL, &addr)) {
|
|
PR_WARNING("Cannot remove neighbor %s\n",
|
|
net_sprint_ipv6_addr(&addr));
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
PR("Neighbor %s removed.\n", net_sprint_ipv6_addr(&addr));
|
|
#else
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
PR_INFO("IPv6 not enabled.\n");
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if defined(CONFIG_NET_IPV6)
|
|
static void nbr_cb(struct net_nbr *nbr, void *user_data)
|
|
{
|
|
struct net_shell_user_data *data = user_data;
|
|
const struct shell *sh = data->sh;
|
|
int *count = data->user_data;
|
|
char *padding = "";
|
|
char *state_pad = "";
|
|
const char *state_str;
|
|
#if defined(CONFIG_NET_IPV6_ND)
|
|
int64_t remaining;
|
|
#endif
|
|
|
|
#if defined(CONFIG_NET_L2_IEEE802154)
|
|
padding = " ";
|
|
#endif
|
|
|
|
if (*count == 0) {
|
|
PR(" Neighbor Interface Flags State "
|
|
"Remain Link %sAddress\n", padding);
|
|
}
|
|
|
|
(*count)++;
|
|
|
|
state_str = net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state);
|
|
|
|
/* This is not a proper way but the minimal libc does not honor
|
|
* string lengths in %s modifier so in order the output to look
|
|
* nice, do it like this.
|
|
*/
|
|
if (strlen(state_str) == 5) {
|
|
state_pad = " ";
|
|
}
|
|
|
|
#if defined(CONFIG_NET_IPV6_ND)
|
|
remaining = net_ipv6_nbr_data(nbr)->reachable +
|
|
net_ipv6_nbr_data(nbr)->reachable_timeout -
|
|
k_uptime_get();
|
|
#endif
|
|
|
|
PR("[%2d] %p %d %5d/%d/%d/%d %s%s %6d %17s%s %s\n",
|
|
*count, nbr, net_if_get_by_iface(nbr->iface),
|
|
net_ipv6_nbr_data(nbr)->link_metric,
|
|
nbr->ref,
|
|
net_ipv6_nbr_data(nbr)->ns_count,
|
|
net_ipv6_nbr_data(nbr)->is_router,
|
|
state_str,
|
|
state_pad,
|
|
#if defined(CONFIG_NET_IPV6_ND)
|
|
(int)(remaining > 0 ? remaining : 0),
|
|
#else
|
|
0,
|
|
#endif
|
|
nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "?" :
|
|
net_sprint_ll_addr(
|
|
net_nbr_get_lladdr(nbr->idx)->addr,
|
|
net_nbr_get_lladdr(nbr->idx)->len),
|
|
nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "" :
|
|
(net_nbr_get_lladdr(nbr->idx)->len == 8U ? "" : padding),
|
|
net_sprint_ipv6_addr(&net_ipv6_nbr_data(nbr)->addr));
|
|
}
|
|
#endif
|
|
|
|
static int cmd_net_nbr(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
#if defined(CONFIG_NET_IPV6)
|
|
int count = 0;
|
|
struct net_shell_user_data user_data;
|
|
#endif
|
|
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
#if defined(CONFIG_NET_IPV6)
|
|
user_data.sh = sh;
|
|
user_data.user_data = &count;
|
|
|
|
net_ipv6_nbr_foreach(nbr_cb, &user_data);
|
|
|
|
if (count == 0) {
|
|
PR("No neighbors.\n");
|
|
}
|
|
#else
|
|
PR_INFO("IPv6 not enabled.\n");
|
|
#endif /* CONFIG_NET_IPV6 */
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION)
|
|
static char nbr_address_buffer[CONFIG_NET_IPV6_MAX_NEIGHBORS][NET_IPV6_ADDR_LEN];
|
|
|
|
static void nbr_address_cb(struct net_nbr *nbr, void *user_data)
|
|
{
|
|
int *count = user_data;
|
|
|
|
if (*count >= CONFIG_NET_IPV6_MAX_NEIGHBORS) {
|
|
return;
|
|
}
|
|
|
|
snprintk(nbr_address_buffer[*count], NET_IPV6_ADDR_LEN,
|
|
"%s", net_sprint_ipv6_addr(&net_ipv6_nbr_data(nbr)->addr));
|
|
|
|
(*count)++;
|
|
}
|
|
|
|
static void nbr_populate_addresses(void)
|
|
{
|
|
int count = 0;
|
|
|
|
net_ipv6_nbr_foreach(nbr_address_cb, &count);
|
|
}
|
|
|
|
static char *set_nbr_address(size_t idx)
|
|
{
|
|
if (idx == 0) {
|
|
memset(nbr_address_buffer, 0, sizeof(nbr_address_buffer));
|
|
nbr_populate_addresses();
|
|
}
|
|
|
|
if (idx >= CONFIG_NET_IPV6_MAX_NEIGHBORS) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!nbr_address_buffer[idx][0]) {
|
|
return NULL;
|
|
}
|
|
|
|
return nbr_address_buffer[idx];
|
|
}
|
|
|
|
static void nbr_address_get(size_t idx, struct shell_static_entry *entry);
|
|
|
|
SHELL_DYNAMIC_CMD_CREATE(nbr_address, nbr_address_get);
|
|
|
|
#define NBR_ADDRESS_CMD &nbr_address
|
|
|
|
static void nbr_address_get(size_t idx, struct shell_static_entry *entry)
|
|
{
|
|
entry->handler = NULL;
|
|
entry->help = NULL;
|
|
entry->subcmd = &nbr_address;
|
|
entry->syntax = set_nbr_address(idx);
|
|
}
|
|
|
|
#else
|
|
#define NBR_ADDRESS_CMD NULL
|
|
#endif /* CONFIG_NET_IPV6 && CONFIG_NET_SHELL_DYN_CMD_COMPLETION */
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_nbr,
|
|
SHELL_CMD(rm, NBR_ADDRESS_CMD,
|
|
"'net nbr rm <address>' removes neighbor from cache.",
|
|
cmd_net_nbr_rm),
|
|
SHELL_SUBCMD_SET_END
|
|
);
|
|
|
|
SHELL_SUBCMD_ADD((net), nbr, &net_cmd_nbr,
|
|
"Print neighbor information.",
|
|
cmd_net_nbr, 1, 0);
|