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>
131 lines
3.2 KiB
C
131 lines
3.2 KiB
C
/*
|
|
* 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"
|
|
#include <zephyr/net/socket.h>
|
|
|
|
#if defined(CONFIG_NET_SOCKETS_OBJ_CORE)
|
|
struct socket_info {
|
|
int opened;
|
|
int closed;
|
|
};
|
|
|
|
int walk_sockets(struct k_obj_core *obj_core, void *user_data)
|
|
{
|
|
#if defined(CONFIG_THREAD_NAME)
|
|
#define THREAD_NAME_LEN CONFIG_THREAD_MAX_NAME_LEN
|
|
#else
|
|
#define THREAD_NAME_LEN 16
|
|
#endif
|
|
struct sock_obj_type_raw_stats stats = { 0 };
|
|
struct net_shell_user_data *data = user_data;
|
|
const struct shell *sh = data->sh;
|
|
struct socket_info *count = data->user_data;
|
|
char thread_name[THREAD_NAME_LEN + 1];
|
|
char fd[5] = { 0 };
|
|
struct sock_obj *obj;
|
|
int lifetime;
|
|
int ret;
|
|
|
|
obj = CONTAINER_OF(obj_core, struct sock_obj, obj_core);
|
|
|
|
if (k_thread_name_copy(obj->creator, thread_name,
|
|
sizeof(thread_name) - 1) < 0) {
|
|
snprintk(thread_name, sizeof(thread_name) - 1, "%p",
|
|
obj->creator);
|
|
}
|
|
|
|
thread_name[sizeof(thread_name) - 1] = '\0';
|
|
|
|
ret = k_obj_core_stats_raw(K_OBJ_CORE(obj),
|
|
&stats, sizeof(stats));
|
|
if (ret != 0) {
|
|
PR_INFO("Failed to get statistics (%d)\n", ret);
|
|
}
|
|
|
|
if (obj->fd < 0) {
|
|
/* Already closed socket. The create time contains the
|
|
* actual lifetime as calculated in close()
|
|
*/
|
|
lifetime = obj->create_time;
|
|
strncat(fd, "C", 1);
|
|
count->closed++;
|
|
} else {
|
|
lifetime = k_ticks_to_ms_ceil32(sys_clock_tick_get() -
|
|
obj->create_time);
|
|
snprintk(fd, sizeof(fd), "%d", obj->fd);
|
|
count->opened++;
|
|
}
|
|
|
|
PR("%16s %-12s %c%c%c\t%-5s%-13d %-10" PRId64 "%-10" PRId64 "\n",
|
|
thread_name, obj->reg->name,
|
|
obj->socket_family == AF_INET6 ? '6' :
|
|
(obj->socket_family ? '4' : ' '),
|
|
obj->socket_type == SOCK_DGRAM ? 'D' :
|
|
(obj->socket_type == SOCK_STREAM ? 'S' :
|
|
(obj->socket_type == SOCK_RAW ? 'R' : ' ')),
|
|
obj->socket_proto == IPPROTO_UDP ? 'U' :
|
|
(obj->socket_proto == IPPROTO_TCP ? 'T' : ' '),
|
|
fd, lifetime, stats.sent, stats.received);
|
|
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_NET_SOCKETS_OBJ_CORE */
|
|
|
|
static int cmd_net_sockets(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
#if defined(CONFIG_NET_SOCKETS_OBJ_CORE)
|
|
struct net_shell_user_data user_data;
|
|
struct k_obj_type *obj_type;
|
|
struct socket_info count = { 0 };
|
|
|
|
user_data.sh = sh;
|
|
user_data.user_data = &count;
|
|
|
|
PR("%16s %-12s %-5s\t%-5s%-14s %-10s%-10s\n",
|
|
"Creator", "Name", "Flags", "FD", "Lifetime (ms)", "Sent",
|
|
"Received");
|
|
PR("\n");
|
|
|
|
obj_type = k_obj_type_find(K_OBJ_TYPE_SOCK);
|
|
k_obj_type_walk_unlocked(obj_type, walk_sockets, (void *)&user_data);
|
|
|
|
if (count.opened == 0 && count.closed == 0) {
|
|
PR("No sockets found.\n");
|
|
} else {
|
|
if (count.opened > 0) {
|
|
PR("\n%d active socket%s found.\n", count.opened,
|
|
count.opened == 1 ? "" : "s");
|
|
}
|
|
|
|
if (count.closed > 0) {
|
|
if (count.opened == 0) {
|
|
PR("\n");
|
|
}
|
|
|
|
PR("%d closed socket%s found.\n", count.closed,
|
|
count.closed == 1 ? "" : "s");
|
|
}
|
|
}
|
|
#else
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
PR_INFO("Set %s to enable %s support.\n",
|
|
"CONFIG_OBJ_CORE and CONFIG_NET_SOCKETS_OBJ_CORE",
|
|
"socket information");
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
SHELL_SUBCMD_ADD((net), sockets, NULL,
|
|
"Show network sockets.",
|
|
cmd_net_sockets, 1, 0);
|