net: shell: Add net-sockets command
The new "net sockets" command will utilize the object core support to track and show information about BSD sockets that are created in the system. This command is able to show info for all network sockets (native, offloaded etc) in the system. Example of the output of the new command: uart:~$ net sockets Creator Name Flags FD Lifetime (ms) Sent Received main af_inet46 6ST 0 3260 819 498 main af_inet46 4ST 1 2110 469 142 main af_inet46 6DU 2 2110 9941 9941 main af_inet46 4DU 3 2110 1375 621 4 active sockets found. Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
This commit is contained in:
parent
7d9f2ad2ca
commit
8a58104396
|
@ -38,6 +38,9 @@ The following net-shell commands are implemented:
|
||||||
"net ping", "Ping a network host."
|
"net ping", "Ping a network host."
|
||||||
"net route", "Show IPv6 network routes. Only available if
|
"net route", "Show IPv6 network routes. Only available if
|
||||||
:kconfig:option:`CONFIG_NET_ROUTE` is set."
|
:kconfig:option:`CONFIG_NET_ROUTE` is set."
|
||||||
|
"net sockets", "Show network socket information and statistics. Only available if
|
||||||
|
:kconfig:option:`CONFIG_NET_SOCKETS_OBJ_CORE` and :kconfig:option:`CONFIG_OBJ_CORE`
|
||||||
|
are set."
|
||||||
"net stats", "Show network statistics."
|
"net stats", "Show network statistics."
|
||||||
"net tcp", "Connect/send data/close TCP connection. Only available if
|
"net tcp", "Connect/send data/close TCP connection. Only available if
|
||||||
:kconfig:option:`CONFIG_NET_TCP` is set."
|
:kconfig:option:`CONFIG_NET_TCP` is set."
|
||||||
|
|
|
@ -23,6 +23,7 @@ zephyr_library_sources(pkt.c)
|
||||||
zephyr_library_sources(ppp.c)
|
zephyr_library_sources(ppp.c)
|
||||||
zephyr_library_sources(resume.c)
|
zephyr_library_sources(resume.c)
|
||||||
zephyr_library_sources(route.c)
|
zephyr_library_sources(route.c)
|
||||||
|
zephyr_library_sources(sockets.c)
|
||||||
zephyr_library_sources(stats.c)
|
zephyr_library_sources(stats.c)
|
||||||
zephyr_library_sources(suspend.c)
|
zephyr_library_sources(suspend.c)
|
||||||
zephyr_library_sources(tcp.c)
|
zephyr_library_sources(tcp.c)
|
||||||
|
|
130
subsys/net/lib/shell/sockets.c
Normal file
130
subsys/net/lib/shell/sockets.c
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* 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);
|
Loading…
Reference in a new issue