blob: 792e34efc21d11c4b1716443b924703c8fbbba1c [file] [log] [blame]
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(net_shell);
#include "common.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);