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>
302 lines
8.0 KiB
C
302 lines
8.0 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"
|
|
|
|
#if defined(CONFIG_NET_TCP)
|
|
#include "tcp_internal.h"
|
|
#include <zephyr/sys/slist.h>
|
|
#endif
|
|
|
|
#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE)
|
|
static void context_cb(struct net_context *context, void *user_data)
|
|
{
|
|
#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
|
|
#define ADDR_LEN NET_IPV6_ADDR_LEN
|
|
#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
|
|
#define ADDR_LEN NET_IPV4_ADDR_LEN
|
|
#else
|
|
#define ADDR_LEN NET_IPV6_ADDR_LEN
|
|
#endif
|
|
struct net_shell_user_data *data = user_data;
|
|
const struct shell *sh = data->sh;
|
|
int *count = data->user_data;
|
|
/* +7 for []:port */
|
|
char addr_local[ADDR_LEN + 7];
|
|
char addr_remote[ADDR_LEN + 7] = "";
|
|
|
|
get_addresses(context, addr_local, sizeof(addr_local),
|
|
addr_remote, sizeof(addr_remote));
|
|
|
|
PR("[%2d] %p\t%d %c%c%c %16s\t%16s\n",
|
|
(*count) + 1, context,
|
|
net_if_get_by_iface(net_context_get_iface(context)),
|
|
net_context_get_family(context) == AF_INET6 ? '6' :
|
|
(net_context_get_family(context) == AF_INET ? '4' : ' '),
|
|
net_context_get_type(context) == SOCK_DGRAM ? 'D' :
|
|
(net_context_get_type(context) == SOCK_STREAM ? 'S' :
|
|
(net_context_get_type(context) == SOCK_RAW ? 'R' : ' ')),
|
|
net_context_get_proto(context) == IPPROTO_UDP ? 'U' :
|
|
(net_context_get_proto(context) == IPPROTO_TCP ? 'T' : ' '),
|
|
addr_local, addr_remote);
|
|
|
|
(*count)++;
|
|
}
|
|
#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */
|
|
|
|
#if CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
static void conn_handler_cb(struct net_conn *conn, void *user_data)
|
|
{
|
|
#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
|
|
#define ADDR_LEN NET_IPV6_ADDR_LEN
|
|
#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
|
|
#define ADDR_LEN NET_IPV4_ADDR_LEN
|
|
#else
|
|
#define ADDR_LEN NET_IPV6_ADDR_LEN
|
|
#endif
|
|
struct net_shell_user_data *data = user_data;
|
|
const struct shell *sh = data->sh;
|
|
int *count = data->user_data;
|
|
/* +7 for []:port */
|
|
char addr_local[ADDR_LEN + 7];
|
|
char addr_remote[ADDR_LEN + 7] = "";
|
|
|
|
if (IS_ENABLED(CONFIG_NET_IPV6) && conn->local_addr.sa_family == AF_INET6) {
|
|
snprintk(addr_local, sizeof(addr_local), "[%s]:%u",
|
|
net_sprint_ipv6_addr(
|
|
&net_sin6(&conn->local_addr)->sin6_addr),
|
|
ntohs(net_sin6(&conn->local_addr)->sin6_port));
|
|
snprintk(addr_remote, sizeof(addr_remote), "[%s]:%u",
|
|
net_sprint_ipv6_addr(
|
|
&net_sin6(&conn->remote_addr)->sin6_addr),
|
|
ntohs(net_sin6(&conn->remote_addr)->sin6_port));
|
|
|
|
} else if (IS_ENABLED(CONFIG_NET_IPV4) && conn->local_addr.sa_family == AF_INET) {
|
|
snprintk(addr_local, sizeof(addr_local), "%s:%d",
|
|
net_sprint_ipv4_addr(
|
|
&net_sin(&conn->local_addr)->sin_addr),
|
|
ntohs(net_sin(&conn->local_addr)->sin_port));
|
|
snprintk(addr_remote, sizeof(addr_remote), "%s:%d",
|
|
net_sprint_ipv4_addr(
|
|
&net_sin(&conn->remote_addr)->sin_addr),
|
|
ntohs(net_sin(&conn->remote_addr)->sin_port));
|
|
|
|
} else if (conn->local_addr.sa_family == AF_UNSPEC) {
|
|
snprintk(addr_local, sizeof(addr_local), "AF_UNSPEC");
|
|
} else {
|
|
snprintk(addr_local, sizeof(addr_local), "AF_UNK(%d)",
|
|
conn->local_addr.sa_family);
|
|
}
|
|
|
|
PR("[%2d] %p %p\t%s\t%16s\t%16s\n",
|
|
(*count) + 1, conn, conn->cb,
|
|
net_proto2str(conn->local_addr.sa_family, conn->proto),
|
|
addr_local, addr_remote);
|
|
|
|
(*count)++;
|
|
}
|
|
#endif /* CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG */
|
|
|
|
#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
struct tcp_detail_info {
|
|
int printed_send_queue_header;
|
|
int printed_details;
|
|
int count;
|
|
};
|
|
#endif
|
|
|
|
#if defined(CONFIG_NET_TCP) && \
|
|
(defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE))
|
|
static void tcp_cb(struct tcp *conn, void *user_data)
|
|
{
|
|
struct net_shell_user_data *data = user_data;
|
|
const struct shell *sh = data->sh;
|
|
int *count = data->user_data;
|
|
uint16_t recv_mss = net_tcp_get_supported_mss(conn);
|
|
|
|
PR("%p %p %5u %5u %10u %10u %5u %s\n",
|
|
conn, conn->context,
|
|
ntohs(net_sin6_ptr(&conn->context->local)->sin6_port),
|
|
ntohs(net_sin6(&conn->context->remote)->sin6_port),
|
|
conn->seq, conn->ack, recv_mss,
|
|
net_tcp_state_str(net_tcp_get_state(conn)));
|
|
|
|
(*count)++;
|
|
}
|
|
|
|
#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
static void tcp_sent_list_cb(struct tcp *conn, void *user_data)
|
|
{
|
|
struct net_shell_user_data *data = user_data;
|
|
const struct shell *sh = data->sh;
|
|
struct tcp_detail_info *details = data->user_data;
|
|
struct net_pkt *pkt;
|
|
sys_snode_t *node;
|
|
|
|
if (conn->state != TCP_LISTEN) {
|
|
if (!details->printed_details) {
|
|
PR("\nTCP Ref Recv_win Send_win Pending "
|
|
"Unacked Flags Queue\n");
|
|
details->printed_details = true;
|
|
}
|
|
|
|
PR("%p %ld %u\t %u\t %zd\t %d\t %d/%d/%d %s\n",
|
|
conn, atomic_get(&conn->ref_count), conn->recv_win,
|
|
conn->send_win, conn->send_data_total, conn->unacked_len,
|
|
conn->in_retransmission, conn->in_connect, conn->in_close,
|
|
sys_slist_is_empty(&conn->send_queue) ? "empty" : "data");
|
|
|
|
details->count++;
|
|
}
|
|
|
|
if (sys_slist_is_empty(&conn->send_queue)) {
|
|
return;
|
|
}
|
|
|
|
if (!details->printed_send_queue_header) {
|
|
PR("\nTCP packets waiting ACK:\n");
|
|
PR("TCP net_pkt[ref/totlen]->net_buf[ref/len]..."
|
|
"\n");
|
|
}
|
|
|
|
PR("%p ", conn);
|
|
|
|
node = sys_slist_peek_head(&conn->send_queue);
|
|
if (node) {
|
|
pkt = CONTAINER_OF(node, struct net_pkt, next);
|
|
if (pkt) {
|
|
struct net_buf *frag = pkt->frags;
|
|
|
|
if (!details->printed_send_queue_header) {
|
|
PR("%p[%ld/%zd]", pkt,
|
|
atomic_get(&pkt->atomic_ref),
|
|
net_pkt_get_len(pkt));
|
|
details->printed_send_queue_header = true;
|
|
} else {
|
|
PR(" %p[%ld/%zd]",
|
|
pkt, atomic_get(&pkt->atomic_ref),
|
|
net_pkt_get_len(pkt));
|
|
}
|
|
|
|
if (frag) {
|
|
PR("->");
|
|
}
|
|
|
|
while (frag) {
|
|
PR("%p[%d/%d]", frag, frag->ref, frag->len);
|
|
|
|
frag = frag->frags;
|
|
if (frag) {
|
|
PR("->");
|
|
}
|
|
}
|
|
|
|
PR("\n");
|
|
}
|
|
}
|
|
|
|
details->printed_send_queue_header = true;
|
|
}
|
|
#endif /* CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG */
|
|
#endif /* TCP */
|
|
|
|
static int cmd_net_conn(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE)
|
|
struct net_shell_user_data user_data;
|
|
int count = 0;
|
|
|
|
PR(" Context \tIface Flags Local Remote\n");
|
|
|
|
user_data.sh = sh;
|
|
user_data.user_data = &count;
|
|
|
|
net_context_foreach(context_cb, &user_data);
|
|
|
|
if (count == 0) {
|
|
PR("No connections\n");
|
|
}
|
|
|
|
#if CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
PR("\n Handler Callback \tProto\tLocal \tRemote\n");
|
|
|
|
count = 0;
|
|
|
|
net_conn_foreach(conn_handler_cb, &user_data);
|
|
|
|
if (count == 0) {
|
|
PR("No connection handlers found.\n");
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_NET_TCP)
|
|
PR("\nTCP Context Src port Dst port "
|
|
"Send-Seq Send-Ack MSS State\n");
|
|
|
|
count = 0;
|
|
|
|
net_tcp_foreach(tcp_cb, &user_data);
|
|
|
|
if (count == 0) {
|
|
PR("No TCP connections\n");
|
|
} else {
|
|
#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG
|
|
/* Print information about pending packets */
|
|
struct tcp_detail_info details;
|
|
|
|
count = 0;
|
|
|
|
if (IS_ENABLED(CONFIG_NET_TCP)) {
|
|
memset(&details, 0, sizeof(details));
|
|
user_data.user_data = &details;
|
|
}
|
|
|
|
net_tcp_foreach(tcp_sent_list_cb, &user_data);
|
|
|
|
if (IS_ENABLED(CONFIG_NET_TCP)) {
|
|
if (details.count == 0) {
|
|
PR("No active connections.\n");
|
|
}
|
|
}
|
|
#endif /* CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG */
|
|
}
|
|
|
|
#if CONFIG_NET_TCP_LOG_LEVEL < LOG_LEVEL_DBG
|
|
PR_INFO("Set %s to enable %s support.\n",
|
|
"CONFIG_NET_TCP_LOG_LEVEL_DBG", "TCP debugging");
|
|
#endif /* CONFIG_NET_TCP_LOG_LEVEL < LOG_LEVEL_DBG */
|
|
|
|
#endif
|
|
|
|
#if defined(CONFIG_NET_IPV6_FRAGMENT)
|
|
count = 0;
|
|
|
|
net_ipv6_frag_foreach(ipv6_frag_cb, &user_data);
|
|
|
|
/* Do not print anything if no fragments are pending atm */
|
|
#endif
|
|
|
|
#else
|
|
PR_INFO("Set %s to enable %s support.\n",
|
|
"CONFIG_NET_OFFLOAD or CONFIG_NET_NATIVE",
|
|
"connection information");
|
|
|
|
#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
SHELL_SUBCMD_ADD((net), conn, NULL, "Print information about network connections.",
|
|
cmd_net_conn, 1, 0);
|