zephyr/subsys/net/lib/shell/nbr.c
Jukka Rissanen 477a4a5d34 net: shell: Rename the common.h to be more unique
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>
2023-12-13 20:13:39 +01:00

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);