blob: 96e882381dfff3908c9e1eb192b22d6a40d68208 [file] [log] [blame]
/** @file
* @brief Network shell module
*
* Provide some networking shell commands that can be useful to applications.
*/
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(net_shell, LOG_LEVEL_DBG);
#include <zephyr/kernel.h>
#include <kernel_internal.h>
#include <zephyr/pm/device.h>
#include <zephyr/random/rand32.h>
#include <stdlib.h>
#include <stdio.h>
#include <zephyr/shell/shell.h>
#include <zephyr/shell/shell_uart.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/dns_resolve.h>
#include <zephyr/net/ppp.h>
#include <zephyr/net/net_stats.h>
#include <zephyr/sys/printk.h>
#include "route.h"
#include "icmpv6.h"
#include "icmpv4.h"
#include "connection.h"
#if defined(CONFIG_NET_TCP)
#include "tcp_internal.h"
#include <zephyr/sys/slist.h>
#endif
#include "ipv6.h"
#if defined(CONFIG_NET_ARP)
#include "ethernet/arp.h"
#endif
#if defined(CONFIG_NET_L2_ETHERNET)
#include <zephyr/net/ethernet.h>
#endif
#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
#include <zephyr/net/ethernet_mgmt.h>
#endif
#if defined(CONFIG_NET_L2_VIRTUAL)
#include <zephyr/net/virtual.h>
#endif
#if defined(CONFIG_NET_L2_VIRTUAL_MGMT)
#include <zephyr/net/virtual_mgmt.h>
#endif
#include <zephyr/net/capture.h>
#if defined(CONFIG_NET_GPTP)
#include <zephyr/net/gptp.h>
#include "ethernet/gptp/gptp_messages.h"
#include "ethernet/gptp/gptp_md.h"
#include "ethernet/gptp/gptp_state.h"
#include "ethernet/gptp/gptp_data_set.h"
#include "ethernet/gptp/gptp_private.h"
#endif
#if defined(CONFIG_NET_L2_PPP)
#include <zephyr/net/ppp.h>
#include "ppp/ppp_internal.h"
#endif
#include "net_shell.h"
#include "net_stats.h"
#include <zephyr/sys/fdtable.h>
#include "websocket/websocket_internal.h"
#define PR(fmt, ...) \
shell_fprintf(shell, SHELL_NORMAL, fmt, ##__VA_ARGS__)
#define PR_SHELL(shell, fmt, ...) \
shell_fprintf(shell, SHELL_NORMAL, fmt, ##__VA_ARGS__)
#define PR_ERROR(fmt, ...) \
shell_fprintf(shell, SHELL_ERROR, fmt, ##__VA_ARGS__)
#define PR_INFO(fmt, ...) \
shell_fprintf(shell, SHELL_INFO, fmt, ##__VA_ARGS__)
#define PR_WARNING(fmt, ...) \
shell_fprintf(shell, SHELL_WARNING, fmt, ##__VA_ARGS__)
#include "net_private.h"
struct net_shell_user_data {
const struct shell *shell;
void *user_data;
};
static inline const char *addrtype2str(enum net_addr_type addr_type)
{
switch (addr_type) {
case NET_ADDR_ANY:
return "<unknown type>";
case NET_ADDR_AUTOCONF:
return "autoconf";
case NET_ADDR_DHCP:
return "DHCP";
case NET_ADDR_MANUAL:
return "manual";
case NET_ADDR_OVERRIDABLE:
return "overridable";
}
return "<invalid type>";
}
static inline const char *addrstate2str(enum net_addr_state addr_state)
{
switch (addr_state) {
case NET_ADDR_ANY_STATE:
return "<unknown state>";
case NET_ADDR_TENTATIVE:
return "tentative";
case NET_ADDR_PREFERRED:
return "preferred";
case NET_ADDR_DEPRECATED:
return "deprecated";
}
return "<invalid state>";
}
static const char *iface2str(struct net_if *iface, const char **extra)
{
#ifdef CONFIG_NET_L2_IEEE802154
if (net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) {
if (extra) {
*extra = "=============";
}
return "IEEE 802.15.4";
}
#endif
#ifdef CONFIG_NET_L2_ETHERNET
if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
if (extra) {
*extra = "========";
}
return "Ethernet";
}
#endif
#ifdef CONFIG_NET_L2_VIRTUAL
if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) {
if (extra) {
*extra = "=======";
}
return "Virtual";
}
#endif
#ifdef CONFIG_NET_L2_PPP
if (net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) {
if (extra) {
*extra = "===";
}
return "PPP";
}
#endif
#ifdef CONFIG_NET_L2_DUMMY
if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
if (extra) {
*extra = "=====";
}
return "Dummy";
}
#endif
#ifdef CONFIG_NET_L2_OPENTHREAD
if (net_if_l2(iface) == &NET_L2_GET_NAME(OPENTHREAD)) {
if (extra) {
*extra = "==========";
}
return "OpenThread";
}
#endif
#ifdef CONFIG_NET_L2_BT
if (net_if_l2(iface) == &NET_L2_GET_NAME(BLUETOOTH)) {
if (extra) {
*extra = "=========";
}
return "Bluetooth";
}
#endif
#ifdef CONFIG_NET_OFFLOAD
if (net_if_is_ip_offloaded(iface)) {
if (extra) {
*extra = "==========";
}
return "IP Offload";
}
#endif
#ifdef CONFIG_NET_L2_CANBUS_RAW
if (net_if_l2(iface) == &NET_L2_GET_NAME(CANBUS_RAW)) {
if (extra) {
*extra = "==========";
}
return "CANBUS_RAW";
}
#endif
if (extra) {
*extra = "==============";
}
return "<unknown type>";
}
#if defined(CONFIG_NET_L2_ETHERNET) && defined(CONFIG_NET_NATIVE)
struct ethernet_capabilities {
enum ethernet_hw_caps capability;
const char * const description;
};
#define EC(cap, desc) { .capability = cap, .description = desc }
static struct ethernet_capabilities eth_hw_caps[] = {
EC(ETHERNET_HW_TX_CHKSUM_OFFLOAD, "TX checksum offload"),
EC(ETHERNET_HW_RX_CHKSUM_OFFLOAD, "RX checksum offload"),
EC(ETHERNET_HW_VLAN, "Virtual LAN"),
EC(ETHERNET_HW_VLAN_TAG_STRIP, "VLAN Tag stripping"),
EC(ETHERNET_AUTO_NEGOTIATION_SET, "Auto negotiation"),
EC(ETHERNET_LINK_10BASE_T, "10 Mbits"),
EC(ETHERNET_LINK_100BASE_T, "100 Mbits"),
EC(ETHERNET_LINK_1000BASE_T, "1 Gbits"),
EC(ETHERNET_DUPLEX_SET, "Half/full duplex"),
EC(ETHERNET_PTP, "IEEE 802.1AS gPTP clock"),
EC(ETHERNET_QAV, "IEEE 802.1Qav (credit shaping)"),
EC(ETHERNET_QBV, "IEEE 802.1Qbv (scheduled traffic)"),
EC(ETHERNET_QBU, "IEEE 802.1Qbu (frame preemption)"),
EC(ETHERNET_TXTIME, "TXTIME"),
EC(ETHERNET_PROMISC_MODE, "Promiscuous mode"),
EC(ETHERNET_PRIORITY_QUEUES, "Priority queues"),
EC(ETHERNET_HW_FILTERING, "MAC address filtering"),
EC(ETHERNET_DSA_SLAVE_PORT, "DSA slave port"),
EC(ETHERNET_DSA_MASTER_PORT, "DSA master port"),
};
static void print_supported_ethernet_capabilities(
const struct shell *shell, struct net_if *iface)
{
enum ethernet_hw_caps caps = net_eth_get_hw_capabilities(iface);
int i;
for (i = 0; i < ARRAY_SIZE(eth_hw_caps); i++) {
if (caps & eth_hw_caps[i].capability) {
PR("\t%s\n", eth_hw_caps[i].description);
}
}
}
#endif /* CONFIG_NET_L2_ETHERNET */
#if defined(CONFIG_NET_NATIVE)
static const char *iface_flags2str(struct net_if *iface)
{
static char str[sizeof("POINTOPOINT") + sizeof("PROMISC") +
sizeof("NO_AUTO_START") + sizeof("SUSPENDED") +
sizeof("MCAST_FORWARD") + sizeof("IPv4") +
sizeof("IPv6")];
int pos = 0;
if (net_if_flag_is_set(iface, NET_IF_POINTOPOINT)) {
pos += snprintk(str + pos, sizeof(str) - pos,
"POINTOPOINT,");
}
if (net_if_flag_is_set(iface, NET_IF_PROMISC)) {
pos += snprintk(str + pos, sizeof(str) - pos,
"PROMISC,");
}
if (net_if_flag_is_set(iface, NET_IF_NO_AUTO_START)) {
pos += snprintk(str + pos, sizeof(str) - pos,
"NO_AUTO_START,");
} else {
pos += snprintk(str + pos, sizeof(str) - pos,
"AUTO_START,");
}
if (net_if_flag_is_set(iface, NET_IF_FORWARD_MULTICASTS)) {
pos += snprintk(str + pos, sizeof(str) - pos,
"MCAST_FORWARD,");
}
if (net_if_flag_is_set(iface, NET_IF_IPV4)) {
pos += snprintk(str + pos, sizeof(str) - pos,
"IPv4,");
}
if (net_if_flag_is_set(iface, NET_IF_IPV6)) {
pos += snprintk(str + pos, sizeof(str) - pos,
"IPv6,");
}
/* get rid of last ',' character */
str[pos - 1] = '\0';
return str;
}
#endif
static void iface_cb(struct net_if *iface, void *user_data)
{
#if defined(CONFIG_NET_NATIVE)
struct net_shell_user_data *data = user_data;
const struct shell *shell = data->shell;
#if defined(CONFIG_NET_IPV6)
struct net_if_ipv6_prefix *prefix;
struct net_if_router *router;
struct net_if_ipv6 *ipv6;
#endif
#if defined(CONFIG_NET_IPV4)
struct net_if_ipv4 *ipv4;
#endif
#if defined(CONFIG_NET_VLAN)
struct ethernet_context *eth_ctx;
#endif
#if defined(CONFIG_NET_IP)
struct net_if_addr *unicast;
struct net_if_mcast_addr *mcast;
#endif
#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
struct ethernet_req_params params;
int ret;
#endif
const char *extra;
#if defined(CONFIG_NET_IP)
int i, count;
#endif
if (data->user_data && data->user_data != iface) {
return;
}
PR("\nInterface %p (%s) [%d]\n", iface, iface2str(iface, &extra),
net_if_get_by_iface(iface));
PR("===========================%s\n", extra);
if (!net_if_is_up(iface)) {
PR_INFO("Interface is down.\n");
/* Show detailed information only when user asks information
* about one specific network interface.
*/
if (data->user_data == NULL) {
return;
}
}
#ifdef CONFIG_NET_POWER_MANAGEMENT
if (net_if_is_suspended(iface)) {
PR_INFO("Interface is suspended, thus not able to tx/rx.\n");
}
#endif
#if defined(CONFIG_NET_L2_VIRTUAL)
if (!sys_slist_is_empty(&iface->config.virtual_interfaces)) {
struct virtual_interface_context *ctx, *tmp;
PR("Virtual interfaces attached to this : ");
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(
&iface->config.virtual_interfaces,
ctx, tmp, node) {
if (ctx->virtual_iface == iface) {
continue;
}
PR("%d ", net_if_get_by_iface(ctx->virtual_iface));
}
PR("\n");
}
if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) {
struct net_if *orig_iface;
char *name, buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN];
name = net_virtual_get_name(iface, buf, sizeof(buf));
if (!(name && name[0])) {
name = "<unknown>";
}
PR("Name : %s\n", name);
orig_iface = net_virtual_get_iface(iface);
if (orig_iface == NULL) {
PR("No attached network interface.\n");
} else {
PR("Attached : %d (%s / %p)\n",
net_if_get_by_iface(orig_iface),
iface2str(orig_iface, NULL),
orig_iface);
}
}
#endif /* CONFIG_NET_L2_VIRTUAL */
if (net_if_get_link_addr(iface) &&
net_if_get_link_addr(iface)->addr) {
PR("Link addr : %s\n",
net_sprint_ll_addr(net_if_get_link_addr(iface)->addr,
net_if_get_link_addr(iface)->len));
}
PR("MTU : %d\n", net_if_get_mtu(iface));
PR("Flags : %s\n", iface_flags2str(iface));
#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
count = 0;
ret = net_mgmt(NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM,
iface, &params,
sizeof(struct ethernet_req_params));
if (!ret && params.priority_queues_num) {
count = params.priority_queues_num;
PR("Priority queues:\n");
for (i = 0; i < count; ++i) {
params.qav_param.queue_id = i;
params.qav_param.type =
ETHERNET_QAV_PARAM_TYPE_STATUS;
ret = net_mgmt(
NET_REQUEST_ETHERNET_GET_QAV_PARAM,
iface, &params,
sizeof(struct ethernet_req_params));
PR("\t%d: Qav ", i);
if (ret) {
PR("not supported\n");
} else {
PR("%s\n",
params.qav_param.enabled ?
"enabled" :
"disabled");
}
}
}
}
#endif
#if defined(CONFIG_NET_PROMISCUOUS_MODE)
PR("Promiscuous mode : %s\n",
net_if_is_promisc(iface) ? "enabled" : "disabled");
#endif
#if defined(CONFIG_NET_VLAN)
if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
eth_ctx = net_if_l2_data(iface);
if (eth_ctx->vlan_enabled) {
for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) {
if (eth_ctx->vlan[i].iface != iface ||
eth_ctx->vlan[i].tag ==
NET_VLAN_TAG_UNSPEC) {
continue;
}
PR("VLAN tag : %d (0x%x)\n",
eth_ctx->vlan[i].tag,
eth_ctx->vlan[i].tag);
}
} else {
PR("VLAN not enabled\n");
}
}
#endif
#ifdef CONFIG_NET_L2_ETHERNET
if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
PR("Ethernet capabilities supported:\n");
print_supported_ethernet_capabilities(shell, iface);
}
#endif /* CONFIG_NET_L2_ETHERNET */
#if defined(CONFIG_NET_IPV6)
count = 0;
if (!net_if_flag_is_set(iface, NET_IF_IPV6)) {
PR("%s not %s for this interface.\n", "IPv6", "enabled");
ipv6 = NULL;
goto skip_ipv6;
}
ipv6 = iface->config.ip.ipv6;
PR("IPv6 unicast addresses (max %d):\n", NET_IF_MAX_IPV6_ADDR);
for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_ADDR; i++) {
unicast = &ipv6->unicast[i];
if (!unicast->is_used) {
continue;
}
PR("\t%s %s %s%s%s\n",
net_sprint_ipv6_addr(&unicast->address.in6_addr),
addrtype2str(unicast->addr_type),
addrstate2str(unicast->addr_state),
unicast->is_infinite ? " infinite" : "",
unicast->is_mesh_local ? " meshlocal" : "");
count++;
}
if (count == 0) {
PR("\t<none>\n");
}
count = 0;
PR("IPv6 multicast addresses (max %d):\n", NET_IF_MAX_IPV6_MADDR);
for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_MADDR; i++) {
mcast = &ipv6->mcast[i];
if (!mcast->is_used) {
continue;
}
PR("\t%s\n", net_sprint_ipv6_addr(&mcast->address.in6_addr));
count++;
}
if (count == 0) {
PR("\t<none>\n");
}
count = 0;
PR("IPv6 prefixes (max %d):\n", NET_IF_MAX_IPV6_PREFIX);
for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_PREFIX; i++) {
prefix = &ipv6->prefix[i];
if (!prefix->is_used) {
continue;
}
PR("\t%s/%d%s\n",
net_sprint_ipv6_addr(&prefix->prefix),
prefix->len, prefix->is_infinite ? " infinite" : "");
count++;
}
if (count == 0) {
PR("\t<none>\n");
}
router = net_if_ipv6_router_find_default(iface, NULL);
if (router) {
PR("IPv6 default router :\n");
PR("\t%s%s\n",
net_sprint_ipv6_addr(&router->address.in6_addr),
router->is_infinite ? " infinite" : "");
}
skip_ipv6:
if (ipv6) {
PR("IPv6 hop limit : %d\n",
ipv6->hop_limit);
PR("IPv6 base reachable time : %d\n",
ipv6->base_reachable_time);
PR("IPv6 reachable time : %d\n",
ipv6->reachable_time);
PR("IPv6 retransmit timer : %d\n",
ipv6->retrans_timer);
}
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
/* No need to print IPv4 information for interface that does not
* support that protocol.
*/
if (
#if defined(CONFIG_NET_L2_IEEE802154)
(net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) ||
#endif
#if defined(CONFIG_NET_L2_BT)
(net_if_l2(iface) == &NET_L2_GET_NAME(BLUETOOTH)) ||
#endif
0) {
PR_WARNING("%s not %s for this interface.\n", "IPv4",
"supported");
return;
}
count = 0;
if (!net_if_flag_is_set(iface, NET_IF_IPV4)) {
PR("%s not %s for this interface.\n", "IPv4", "enabled");
ipv4 = NULL;
goto skip_ipv4;
}
ipv4 = iface->config.ip.ipv4;
PR("IPv4 unicast addresses (max %d):\n", NET_IF_MAX_IPV4_ADDR);
for (i = 0; ipv4 && i < NET_IF_MAX_IPV4_ADDR; i++) {
unicast = &ipv4->unicast[i];
if (!unicast->is_used) {
continue;
}
PR("\t%s %s %s%s\n",
net_sprint_ipv4_addr(&unicast->address.in_addr),
addrtype2str(unicast->addr_type),
addrstate2str(unicast->addr_state),
unicast->is_infinite ? " infinite" : "");
count++;
}
if (count == 0) {
PR("\t<none>\n");
}
count = 0;
PR("IPv4 multicast addresses (max %d):\n", NET_IF_MAX_IPV4_MADDR);
for (i = 0; ipv4 && i < NET_IF_MAX_IPV4_MADDR; i++) {
mcast = &ipv4->mcast[i];
if (!mcast->is_used) {
continue;
}
PR("\t%s\n", net_sprint_ipv4_addr(&mcast->address.in_addr));
count++;
}
if (count == 0) {
PR("\t<none>\n");
}
skip_ipv4:
if (ipv4) {
PR("IPv4 gateway : %s\n",
net_sprint_ipv4_addr(&ipv4->gw));
PR("IPv4 netmask : %s\n",
net_sprint_ipv4_addr(&ipv4->netmask));
}
#endif /* CONFIG_NET_IPV4 */
#if defined(CONFIG_NET_DHCPV4)
PR("DHCPv4 lease time : %u\n",
iface->config.dhcpv4.lease_time);
PR("DHCPv4 renew time : %u\n",
iface->config.dhcpv4.renewal_time);
PR("DHCPv4 server : %s\n",
net_sprint_ipv4_addr(&iface->config.dhcpv4.server_id));
PR("DHCPv4 requested : %s\n",
net_sprint_ipv4_addr(&iface->config.dhcpv4.requested_ip));
PR("DHCPv4 state : %s\n",
net_dhcpv4_state_name(iface->config.dhcpv4.state));
PR("DHCPv4 attempts : %d\n",
iface->config.dhcpv4.attempts);
#endif /* CONFIG_NET_DHCPV4 */
#else
ARG_UNUSED(iface);
ARG_UNUSED(user_data);
#endif /* CONFIG_NET_NATIVE */
}
#if defined(CONFIG_NET_ROUTE) && defined(CONFIG_NET_NATIVE)
static void route_cb(struct net_route_entry *entry, void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *shell = data->shell;
struct net_if *iface = data->user_data;
struct net_route_nexthop *nexthop_route;
int count;
uint32_t now = k_uptime_get_32();
if (entry->iface != iface) {
return;
}
PR("IPv6 prefix : %s/%d\n", net_sprint_ipv6_addr(&entry->addr),
entry->prefix_len);
count = 0;
SYS_SLIST_FOR_EACH_CONTAINER(&entry->nexthop, nexthop_route, node) {
struct net_linkaddr_storage *lladdr;
char remaining_str[sizeof("01234567890 sec")];
uint32_t remaining;
if (!nexthop_route->nbr) {
continue;
}
PR("\tneighbor : %p\t", nexthop_route->nbr);
if (nexthop_route->nbr->idx == NET_NBR_LLADDR_UNKNOWN) {
PR("addr : <unknown>\t");
} else {
lladdr = net_nbr_get_lladdr(nexthop_route->nbr->idx);
PR("addr : %s\t", net_sprint_ll_addr(lladdr->addr,
lladdr->len));
}
if (entry->is_infinite) {
snprintk(remaining_str, sizeof(remaining_str) - 1,
"infinite");
} else {
remaining = net_timeout_remaining(&entry->lifetime, now);
snprintk(remaining_str, sizeof(remaining_str) - 1,
"%u sec", remaining);
}
PR("lifetime : %s\n", remaining_str);
count++;
}
if (count == 0) {
PR("\t<none>\n");
}
}
static void iface_per_route_cb(struct net_if *iface, void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *shell = data->shell;
const char *extra;
PR("\nIPv6 routes for interface %d (%p) (%s)\n",
net_if_get_by_iface(iface), iface,
iface2str(iface, &extra));
PR("=========================================%s\n", extra);
data->user_data = iface;
net_route_foreach(route_cb, data);
}
#endif /* CONFIG_NET_ROUTE */
#if defined(CONFIG_NET_ROUTE_MCAST) && defined(CONFIG_NET_NATIVE)
static void route_mcast_cb(struct net_route_entry_mcast *entry,
void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *shell = data->shell;
struct net_if *iface = data->user_data;
const char *extra;
if (entry->iface != iface) {
return;
}
PR("IPv6 multicast route %p for interface %d (%p) (%s)\n", entry,
net_if_get_by_iface(iface), iface, iface2str(iface, &extra));
PR("==========================================================="
"%s\n", extra);
PR("IPv6 group : %s\n", net_sprint_ipv6_addr(&entry->group));
PR("IPv6 group len : %d\n", entry->prefix_len);
PR("Lifetime : %u\n", entry->lifetime);
}
static void iface_per_mcast_route_cb(struct net_if *iface, void *user_data)
{
struct net_shell_user_data *data = user_data;
data->user_data = iface;
net_route_mcast_foreach(route_mcast_cb, NULL, data);
}
#endif /* CONFIG_NET_ROUTE_MCAST */
#if defined(CONFIG_NET_STATISTICS)
#if NET_TC_COUNT > 1
static const char *priority2str(enum net_priority priority)
{
switch (priority) {
case NET_PRIORITY_BK:
return "BK"; /* Background */
case NET_PRIORITY_BE:
return "BE"; /* Best effort */
case NET_PRIORITY_EE:
return "EE"; /* Excellent effort */
case NET_PRIORITY_CA:
return "CA"; /* Critical applications */
case NET_PRIORITY_VI:
return "VI"; /* Video, < 100 ms latency and jitter */
case NET_PRIORITY_VO:
return "VO"; /* Voice, < 10 ms latency and jitter */
case NET_PRIORITY_IC:
return "IC"; /* Internetwork control */
case NET_PRIORITY_NC:
return "NC"; /* Network control */
}
return "??";
}
#endif
#if defined(CONFIG_NET_STATISTICS_ETHERNET) && \
defined(CONFIG_NET_STATISTICS_USER_API)
static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data,
const struct shell *shell)
{
PR("Statistics for Ethernet interface %p [%d]\n", iface,
net_if_get_by_iface(iface));
PR("Bytes received : %u\n", data->bytes.received);
PR("Bytes sent : %u\n", data->bytes.sent);
PR("Packets received : %u\n", data->pkts.rx);
PR("Packets sent : %u\n", data->pkts.tx);
PR("Bcast received : %u\n", data->broadcast.rx);
PR("Bcast sent : %u\n", data->broadcast.tx);
PR("Mcast received : %u\n", data->multicast.rx);
PR("Mcast sent : %u\n", data->multicast.tx);
#if defined(CONFIG_NET_STATISTICS_ETHERNET_VENDOR)
if (data->vendor) {
PR("Vendor specific statistics for Ethernet "
"interface %p [%d]:\n",
iface, net_if_get_by_iface(iface));
size_t i = 0;
do {
PR("%s : %u\n", data->vendor[i].key,
data->vendor[i].value);
i++;
} while (data->vendor[i].key);
}
#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */
}
#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */
#if defined(CONFIG_NET_STATISTICS_PPP) && \
defined(CONFIG_NET_STATISTICS_USER_API)
static void print_ppp_stats(struct net_if *iface, struct net_stats_ppp *data,
const struct shell *shell)
{
PR("Frames recv %u\n", data->pkts.rx);
PR("Frames sent %u\n", data->pkts.tx);
PR("Frames dropped %u\n", data->drop);
PR("Bad FCS %u\n", data->chkerr);
}
#endif /* CONFIG_NET_STATISTICS_PPP && CONFIG_NET_STATISTICS_USER_API */
#if !defined(CONFIG_NET_NATIVE)
#define GET_STAT(a, b) 0
#endif
#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) || \
defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
#if (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1)
static char *get_net_pkt_tc_stats_detail(struct net_if *iface, int i,
bool is_tx)
{
static char extra_stats[sizeof("\t[0=xxxx us]") +
sizeof("->xxxx") *
NET_PKT_DETAIL_STATS_COUNT];
int j, total = 0, pos = 0;
pos += snprintk(extra_stats, sizeof(extra_stats), "\t[0");
for (j = 0; j < NET_PKT_DETAIL_STATS_COUNT; j++) {
net_stats_t count = 0;
uint32_t avg;
if (is_tx) {
#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) && (NET_TC_TX_COUNT > 1)
count = GET_STAT(iface,
tc.sent[i].tx_time_detail[j].count);
#endif
} else {
#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) && (NET_TC_RX_COUNT > 1)
count = GET_STAT(iface,
tc.recv[i].rx_time_detail[j].count);
#endif
}
if (count == 0) {
break;
}
if (is_tx) {
#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) && (NET_TC_TX_COUNT > 1)
avg = (uint32_t)(GET_STAT(iface,
tc.sent[i].tx_time_detail[j].sum) /
(uint64_t)count);
#endif
} else {
#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) && (NET_TC_RX_COUNT > 1)
avg = (uint32_t)(GET_STAT(iface,
tc.recv[i].rx_time_detail[j].sum) /
(uint64_t)count);
#endif
}
if (avg == 0) {
continue;
}
total += avg;
pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos,
"->%u", avg);
}
if (total == 0U) {
return "\0";
}
pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos,
"=%u us]", total);
return extra_stats;
}
#endif /* (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1) */
#if (NET_TC_TX_COUNT <= 1) || (NET_TC_RX_COUNT <= 1)
static char *get_net_pkt_stats_detail(struct net_if *iface, bool is_tx)
{
static char extra_stats[sizeof("\t[0=xxxx us]") + sizeof("->xxxx") *
NET_PKT_DETAIL_STATS_COUNT];
int j, total = 0, pos = 0;
pos += snprintk(extra_stats, sizeof(extra_stats), "\t[0");
for (j = 0; j < NET_PKT_DETAIL_STATS_COUNT; j++) {
net_stats_t count;
uint32_t avg;
if (is_tx) {
#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
count = GET_STAT(iface, tx_time_detail[j].count);
#endif
} else {
#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
count = GET_STAT(iface, rx_time_detail[j].count);
#endif
}
if (count == 0) {
break;
}
if (is_tx) {
#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
avg = (uint32_t)(GET_STAT(iface,
tx_time_detail[j].sum) /
(uint64_t)count);
#endif
} else {
#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
avg = (uint32_t)(GET_STAT(iface,
rx_time_detail[j].sum) /
(uint64_t)count);
#endif
}
if (avg == 0) {
continue;
}
total += avg;
pos += snprintk(extra_stats + pos,
sizeof(extra_stats) - pos,
"->%u", avg);
}
if (total == 0U) {
return "\0";
}
pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos,
"=%u us]", total);
return extra_stats;
}
#endif /* (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1) */
#else /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL ||
CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
#if defined(CONFIG_NET_PKT_TXTIME_STATS) || \
defined(CONFIG_NET_PKT_RXTIME_STATS)
#if (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1)
static char *get_net_pkt_tc_stats_detail(struct net_if *iface, int i,
bool is_tx)
{
ARG_UNUSED(iface);
ARG_UNUSED(i);
ARG_UNUSED(is_tx);
return "\0";
}
#endif
#if (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1)
static char *get_net_pkt_stats_detail(struct net_if *iface, bool is_tx)
{
ARG_UNUSED(iface);
ARG_UNUSED(is_tx);
return "\0";
}
#endif
#endif /* CONFIG_NET_PKT_TXTIME_STATS) || CONFIG_NET_PKT_RXTIME_STATS */
#endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL ||
CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
static void print_tc_tx_stats(const struct shell *shell, struct net_if *iface)
{
#if NET_TC_TX_COUNT > 1
int i;
PR("TX traffic class statistics:\n");
#if defined(CONFIG_NET_PKT_TXTIME_STATS)
PR("TC Priority\tSent pkts\tbytes\ttime\n");
for (i = 0; i < NET_TC_TX_COUNT; i++) {
net_stats_t count = GET_STAT(iface,
tc.sent[i].tx_time.count);
if (count == 0) {
PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i,
priority2str(GET_STAT(iface, tc.sent[i].priority)),
GET_STAT(iface, tc.sent[i].priority),
GET_STAT(iface, tc.sent[i].pkts),
GET_STAT(iface, tc.sent[i].bytes));
} else {
PR("[%d] %s (%d)\t%d\t\t%d\t%u us%s\n", i,
priority2str(GET_STAT(iface, tc.sent[i].priority)),
GET_STAT(iface, tc.sent[i].priority),
GET_STAT(iface, tc.sent[i].pkts),
GET_STAT(iface, tc.sent[i].bytes),
(uint32_t)(GET_STAT(iface,
tc.sent[i].tx_time.sum) /
(uint64_t)count),
get_net_pkt_tc_stats_detail(iface, i, true));
}
}
#else
PR("TC Priority\tSent pkts\tbytes\n");
for (i = 0; i < NET_TC_TX_COUNT; i++) {
PR("[%d] %s (%d)\t%d\t\t%d\n", i,
priority2str(GET_STAT(iface, tc.sent[i].priority)),
GET_STAT(iface, tc.sent[i].priority),
GET_STAT(iface, tc.sent[i].pkts),
GET_STAT(iface, tc.sent[i].bytes));
}
#endif /* CONFIG_NET_PKT_TXTIME_STATS */
#else
ARG_UNUSED(shell);
#if defined(CONFIG_NET_PKT_TXTIME_STATS)
net_stats_t count = GET_STAT(iface, tx_time.count);
if (count != 0) {
PR("Avg %s net_pkt (%u) time %lu us%s\n", "TX", count,
(uint32_t)(GET_STAT(iface, tx_time.sum) / (uint64_t)count),
get_net_pkt_stats_detail(iface, true));
}
#else
ARG_UNUSED(iface);
#endif /* CONFIG_NET_PKT_TXTIME_STATS */
#endif /* NET_TC_TX_COUNT > 1 */
}
static void print_tc_rx_stats(const struct shell *shell, struct net_if *iface)
{
#if NET_TC_RX_COUNT > 1
int i;
PR("RX traffic class statistics:\n");
#if defined(CONFIG_NET_PKT_RXTIME_STATS)
PR("TC Priority\tRecv pkts\tbytes\ttime\n");
for (i = 0; i < NET_TC_RX_COUNT; i++) {
net_stats_t count = GET_STAT(iface,
tc.recv[i].rx_time.count);
if (count == 0) {
PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i,
priority2str(GET_STAT(iface, tc.recv[i].priority)),
GET_STAT(iface, tc.recv[i].priority),
GET_STAT(iface, tc.recv[i].pkts),
GET_STAT(iface, tc.recv[i].bytes));
} else {
PR("[%d] %s (%d)\t%d\t\t%d\t%u us%s\n", i,
priority2str(GET_STAT(iface, tc.recv[i].priority)),
GET_STAT(iface, tc.recv[i].priority),
GET_STAT(iface, tc.recv[i].pkts),
GET_STAT(iface, tc.recv[i].bytes),
(uint32_t)(GET_STAT(iface,
tc.recv[i].rx_time.sum) /
(uint64_t)count),
get_net_pkt_tc_stats_detail(iface, i, false));
}
}
#else
PR("TC Priority\tRecv pkts\tbytes\n");
for (i = 0; i < NET_TC_RX_COUNT; i++) {
PR("[%d] %s (%d)\t%d\t\t%d\n", i,
priority2str(GET_STAT(iface, tc.recv[i].priority)),
GET_STAT(iface, tc.recv[i].priority),
GET_STAT(iface, tc.recv[i].pkts),
GET_STAT(iface, tc.recv[i].bytes));
}
#endif /* CONFIG_NET_PKT_RXTIME_STATS */
#else
ARG_UNUSED(shell);
#if defined(CONFIG_NET_PKT_RXTIME_STATS)
net_stats_t count = GET_STAT(iface, rx_time.count);
if (count != 0) {
PR("Avg %s net_pkt (%u) time %lu us%s\n", "RX", count,
(uint32_t)(GET_STAT(iface, rx_time.sum) / (uint64_t)count),
get_net_pkt_stats_detail(iface, false));
}
#else
ARG_UNUSED(iface);
#endif /* CONFIG_NET_PKT_RXTIME_STATS */
#endif /* NET_TC_RX_COUNT > 1 */
}
static void print_net_pm_stats(const struct shell *shell, struct net_if *iface)
{
#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT)
PR("PM suspend stats:\n");
PR("\tLast time : %u ms\n",
GET_STAT(iface, pm.last_suspend_time));
PR("\tAverage time : %u ms\n",
(uint32_t)(GET_STAT(iface, pm.overall_suspend_time) /
GET_STAT(iface, pm.suspend_count)));
PR("\tTotal time : %" PRIu64 " ms\n",
GET_STAT(iface, pm.overall_suspend_time));
PR("\tHow many times: %u\n",
GET_STAT(iface, pm.suspend_count));
#else
ARG_UNUSED(shell);
ARG_UNUSED(iface);
#endif
}
static void net_shell_print_statistics(struct net_if *iface, void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *shell = data->shell;
if (iface) {
const char *extra;
PR("\nInterface %p (%s) [%d]\n", iface,
iface2str(iface, &extra), net_if_get_by_iface(iface));
PR("===========================%s\n", extra);
} else {
PR("\nGlobal statistics\n");
PR("=================\n");
}
#if defined(CONFIG_NET_STATISTICS_IPV6) && defined(CONFIG_NET_NATIVE_IPV6)
PR("IPv6 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
GET_STAT(iface, ipv6.recv),
GET_STAT(iface, ipv6.sent),
GET_STAT(iface, ipv6.drop),
GET_STAT(iface, ipv6.forwarded));
#if defined(CONFIG_NET_STATISTICS_IPV6_ND)
PR("IPv6 ND recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(iface, ipv6_nd.recv),
GET_STAT(iface, ipv6_nd.sent),
GET_STAT(iface, ipv6_nd.drop));
#endif /* CONFIG_NET_STATISTICS_IPV6_ND */
#if defined(CONFIG_NET_STATISTICS_MLD)
PR("IPv6 MLD recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(iface, ipv6_mld.recv),
GET_STAT(iface, ipv6_mld.sent),
GET_STAT(iface, ipv6_mld.drop));
#endif /* CONFIG_NET_STATISTICS_MLD */
#endif /* CONFIG_NET_STATISTICS_IPV6 */
#if defined(CONFIG_NET_STATISTICS_IPV4) && defined(CONFIG_NET_NATIVE_IPV4)
PR("IPv4 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
GET_STAT(iface, ipv4.recv),
GET_STAT(iface, ipv4.sent),
GET_STAT(iface, ipv4.drop),
GET_STAT(iface, ipv4.forwarded));
#endif /* CONFIG_NET_STATISTICS_IPV4 */
PR("IP vhlerr %d\thblener\t%d\tlblener\t%d\n",
GET_STAT(iface, ip_errors.vhlerr),
GET_STAT(iface, ip_errors.hblenerr),
GET_STAT(iface, ip_errors.lblenerr));
PR("IP fragerr %d\tchkerr\t%d\tprotoer\t%d\n",
GET_STAT(iface, ip_errors.fragerr),
GET_STAT(iface, ip_errors.chkerr),
GET_STAT(iface, ip_errors.protoerr));
#if defined(CONFIG_NET_STATISTICS_ICMP) && defined(CONFIG_NET_NATIVE_IPV4)
PR("ICMP recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(iface, icmp.recv),
GET_STAT(iface, icmp.sent),
GET_STAT(iface, icmp.drop));
PR("ICMP typeer %d\tchkerr\t%d\n",
GET_STAT(iface, icmp.typeerr),
GET_STAT(iface, icmp.chkerr));
#endif
#if defined(CONFIG_NET_STATISTICS_IGMP)
PR("IGMP recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(iface, ipv4_igmp.recv),
GET_STAT(iface, ipv4_igmp.sent),
GET_STAT(iface, ipv4_igmp.drop));
#endif /* CONFIG_NET_STATISTICS_IGMP */
#if defined(CONFIG_NET_STATISTICS_UDP) && defined(CONFIG_NET_NATIVE_UDP)
PR("UDP recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(iface, udp.recv),
GET_STAT(iface, udp.sent),
GET_STAT(iface, udp.drop));
PR("UDP chkerr %d\n",
GET_STAT(iface, udp.chkerr));
#endif
#if defined(CONFIG_NET_STATISTICS_TCP) && defined(CONFIG_NET_NATIVE_TCP)
PR("TCP bytes recv %u\tsent\t%d\tresent\t%d\n",
GET_STAT(iface, tcp.bytes.received),
GET_STAT(iface, tcp.bytes.sent),
GET_STAT(iface, tcp.resent));
PR("TCP seg recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(iface, tcp.recv),
GET_STAT(iface, tcp.sent),
GET_STAT(iface, tcp.seg_drop));
PR("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n",
GET_STAT(iface, tcp.rexmit),
GET_STAT(iface, tcp.chkerr),
GET_STAT(iface, tcp.ackerr));
PR("TCP seg rsterr %d\trst\t%d\n",
GET_STAT(iface, tcp.rsterr),
GET_STAT(iface, tcp.rst));
PR("TCP conn drop %d\tconnrst\t%d\n",
GET_STAT(iface, tcp.conndrop),
GET_STAT(iface, tcp.connrst));
PR("TCP pkt drop %d\n", GET_STAT(iface, tcp.drop));
#endif
PR("Bytes received %u\n", GET_STAT(iface, bytes.received));
PR("Bytes sent %u\n", GET_STAT(iface, bytes.sent));
PR("Processing err %d\n", GET_STAT(iface, processing_error));
print_tc_tx_stats(shell, iface);
print_tc_rx_stats(shell, iface);
#if defined(CONFIG_NET_STATISTICS_ETHERNET) && \
defined(CONFIG_NET_STATISTICS_USER_API)
if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
struct net_stats_eth eth_data;
int ret;
ret = net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, iface,
&eth_data, sizeof(eth_data));
if (!ret) {
print_eth_stats(iface, &eth_data, shell);
}
}
#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */
#if defined(CONFIG_NET_STATISTICS_PPP) && \
defined(CONFIG_NET_STATISTICS_USER_API)
if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) {
struct net_stats_ppp ppp_data;
int ret;
ret = net_mgmt(NET_REQUEST_STATS_GET_PPP, iface,
&ppp_data, sizeof(ppp_data));
if (!ret) {
print_ppp_stats(iface, &ppp_data, shell);
}
}
#endif /* CONFIG_NET_STATISTICS_PPP && CONFIG_NET_STATISTICS_USER_API */
print_net_pm_stats(shell, iface);
}
#endif /* CONFIG_NET_STATISTICS */
#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE)
static void get_addresses(struct net_context *context,
char addr_local[], int local_len,
char addr_remote[], int remote_len)
{
#if defined(CONFIG_NET_IPV6)
if (context->local.family == AF_INET6) {
snprintk(addr_local, local_len, "[%s]:%u",
net_sprint_ipv6_addr(
net_sin6_ptr(&context->local)->sin6_addr),
ntohs(net_sin6_ptr(&context->local)->sin6_port));
snprintk(addr_remote, remote_len, "[%s]:%u",
net_sprint_ipv6_addr(
&net_sin6(&context->remote)->sin6_addr),
ntohs(net_sin6(&context->remote)->sin6_port));
} else
#endif
#if defined(CONFIG_NET_IPV4)
if (context->local.family == AF_INET) {
snprintk(addr_local, local_len, "%s:%d",
net_sprint_ipv4_addr(
net_sin_ptr(&context->local)->sin_addr),
ntohs(net_sin_ptr(&context->local)->sin_port));
snprintk(addr_remote, remote_len, "%s:%d",
net_sprint_ipv4_addr(
&net_sin(&context->remote)->sin_addr),
ntohs(net_sin(&context->remote)->sin_port));
} else
#endif
if (context->local.family == AF_UNSPEC) {
snprintk(addr_local, local_len, "AF_UNSPEC");
} else if (context->local.family == AF_PACKET) {
snprintk(addr_local, local_len, "AF_PACKET");
} else if (context->local.family == AF_CAN) {
snprintk(addr_local, local_len, "AF_CAN");
} else {
snprintk(addr_local, local_len, "AF_UNK(%d)",
context->local.family);
}
}
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 *shell = data->shell;
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 *shell = data->shell;
int *count = data->user_data;
/* +7 for []:port */
char addr_local[ADDR_LEN + 7];
char addr_remote[ADDR_LEN + 7] = "";
#if defined(CONFIG_NET_IPV6)
if (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
#endif
#if defined(CONFIG_NET_IPV4)
if (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
#endif
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 *shell = data->shell;
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 *shell = data->shell;
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 */
#if defined(CONFIG_NET_IPV6_FRAGMENT)
static void ipv6_frag_cb(struct net_ipv6_reassembly *reass,
void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *shell = data->shell;
int *count = data->user_data;
char src[ADDR_LEN];
int i;
if (!*count) {
PR("\nIPv6 reassembly Id Remain "
"Src \tDst\n");
}
snprintk(src, ADDR_LEN, "%s", net_sprint_ipv6_addr(&reass->src));
PR("%p 0x%08x %5d %16s\t%16s\n", reass, reass->id,
k_ticks_to_ms_ceil32(k_work_delayable_remaining_get(&reass->timer)),
src, net_sprint_ipv6_addr(&reass->dst));
for (i = 0; i < CONFIG_NET_IPV6_FRAGMENT_MAX_PKT; i++) {
if (reass->pkt[i]) {
struct net_buf *frag = reass->pkt[i]->frags;
PR("[%d] pkt %p->", i, reass->pkt[i]);
while (frag) {
PR("%p", frag);
frag = frag->frags;
if (frag) {
PR("->");
}
}
PR("\n");
}
}
(*count)++;
}
#endif /* CONFIG_NET_IPV6_FRAGMENT */
#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
static void allocs_cb(struct net_pkt *pkt,
struct net_buf *buf,
const char *func_alloc,
int line_alloc,
const char *func_free,
int line_free,
bool in_use,
void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *shell = data->shell;
const char *str;
if (in_use) {
str = "used";
} else {
if (func_alloc) {
str = "free";
} else {
str = "avail";
}
}
if (buf) {
goto buf;
}
if (func_alloc) {
if (in_use) {
PR("%p/%ld\t%5s\t%5s\t%s():%d\n",
pkt, atomic_get(&pkt->atomic_ref), str,
net_pkt_slab2str(pkt->slab),
func_alloc, line_alloc);
} else {
PR("%p\t%5s\t%5s\t%s():%d -> %s():%d\n",
pkt, str, net_pkt_slab2str(pkt->slab),
func_alloc, line_alloc, func_free,
line_free);
}
}
return;
buf:
if (func_alloc) {
struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
if (in_use) {
PR("%p/%d\t%5s\t%5s\t%s():%d\n",
buf, buf->ref,
str, net_pkt_pool2str(pool), func_alloc,
line_alloc);
} else {
PR("%p\t%5s\t%5s\t%s():%d -> %s():%d\n",
buf, str, net_pkt_pool2str(pool),
func_alloc, line_alloc, func_free,
line_free);
}
}
}
#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */
/* Put the actual shell commands after this */
static int cmd_net_allocs(const struct shell *shell, size_t argc, char *argv[])
{
#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
struct net_shell_user_data user_data;
#endif
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
user_data.shell = shell;
PR("Network memory allocations\n\n");
PR("memory\t\tStatus\tPool\tFunction alloc -> freed\n");
net_pkt_allocs_foreach(allocs_cb, &user_data);
#else
PR_INFO("Set %s to enable %s support.\n",
"CONFIG_NET_DEBUG_NET_PKT_ALLOC", "net_pkt allocation");
#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */
return 0;
}
#if defined(CONFIG_NET_ARP) && defined(CONFIG_NET_NATIVE)
static void arp_cb(struct arp_entry *entry, void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *shell = data->shell;
int *count = data->user_data;
if (*count == 0) {
PR(" Interface Link Address\n");
}
PR("[%2d] %d %s %s\n", *count,
net_if_get_by_iface(entry->iface),
net_sprint_ll_addr(entry->eth.addr, sizeof(struct net_eth_addr)),
net_sprint_ipv4_addr(&entry->ip));
(*count)++;
}
#endif /* CONFIG_NET_ARP */
#if !defined(CONFIG_NET_ARP)
static void print_arp_error(const struct shell *shell)
{
PR_INFO("Set %s to enable %s support.\n",
"CONFIG_NET_NATIVE, CONFIG_NET_ARP, CONFIG_NET_IPV4 and"
" CONFIG_NET_L2_ETHERNET", "ARP");
}
#endif
static int cmd_net_arp(const struct shell *shell, size_t argc, char *argv[])
{
#if defined(CONFIG_NET_ARP)
struct net_shell_user_data user_data;
int arg = 1;
#endif
ARG_UNUSED(argc);
#if defined(CONFIG_NET_ARP)
if (!argv[arg]) {
/* ARP cache content */
int count = 0;
user_data.shell = shell;
user_data.user_data = &count;
if (net_arp_foreach(arp_cb, &user_data) == 0) {
PR("ARP cache is empty.\n");
}
}
#else
print_arp_error(shell);
#endif
return 0;
}
static int cmd_net_arp_flush(const struct shell *shell, size_t argc,
char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_ARP)
PR("Flushing ARP cache.\n");
net_arp_clear_cache(NULL);
#else
print_arp_error(shell);
#endif
return 0;
}
#if defined(CONFIG_NET_CAPTURE)
static const struct device *capture_dev;
static void get_address_str(const struct sockaddr *addr,
char *str, int str_len)
{
if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == AF_INET6) {
snprintk(str, str_len, "[%s]:%u",
net_sprint_ipv6_addr(&net_sin6(addr)->sin6_addr),
ntohs(net_sin6(addr)->sin6_port));
} else if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) {
snprintk(str, str_len, "%s:%d",
net_sprint_ipv4_addr(&net_sin(addr)->sin_addr),
ntohs(net_sin(addr)->sin_port));
} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
addr->sa_family == AF_PACKET) {
snprintk(str, str_len, "AF_PACKET");
} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
addr->sa_family == AF_CAN) {
snprintk(str, str_len, "AF_CAN");
} else if (addr->sa_family == AF_UNSPEC) {
snprintk(str, str_len, "AF_UNSPEC");
} else {
snprintk(str, str_len, "AF_UNK(%d)", addr->sa_family);
}
}
static void capture_cb(struct net_capture_info *info, void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *shell = data->shell;
int *count = data->user_data;
char addr_local[ADDR_LEN + 7];
char addr_peer[ADDR_LEN + 7];
if (*count == 0) {
PR(" \t\tCapture Tunnel\n");
PR("Device\t\tiface iface Local\t\t\tPeer\n");
}
get_address_str(info->local, addr_local, sizeof(addr_local));
get_address_str(info->peer, addr_peer, sizeof(addr_peer));
PR("%s\t%c %d %s\t%s\n", info->capture_dev->name,
info->is_enabled ?
(net_if_get_by_iface(info->capture_iface) + '0') : '-',
net_if_get_by_iface(info->tunnel_iface),
addr_local, addr_peer);
(*count)++;
}
#endif
static int cmd_net_capture(const struct shell *shell, size_t argc,
char *argv[])
{
#if defined(CONFIG_NET_CAPTURE)
bool ret;
if (capture_dev == NULL) {
PR_INFO("Network packet capture %s\n", "not configured");
} else {
struct net_shell_user_data user_data;
int count = 0;
ret = net_capture_is_enabled(capture_dev);
PR_INFO("Network packet capture %s\n",
ret ? "enabled" : "disabled");
user_data.shell = shell;
user_data.user_data = &count;
net_capture_foreach(capture_cb, &user_data);
}
#else
ARG_UNUSED(argc);
ARG_UNUSED(argv);
PR_INFO("Set %s to enable %s support.\n",
"CONFIG_NET_CAPTURE", "network packet capture");
#endif
return 0;
}
static int cmd_net_capture_setup(const struct shell *shell, size_t argc,
char *argv[])
{
#if defined(CONFIG_NET_CAPTURE)
int ret, arg = 1;
const char *remote, *local, *peer;
remote = argv[arg++];
if (!remote) {
PR_WARNING("Remote IP address not specified.\n");
return -ENOEXEC;
}
local = argv[arg++];
if (!local) {
PR_WARNING("Local IP address not specified.\n");
return -ENOEXEC;
}
peer = argv[arg];
if (!peer) {
PR_WARNING("Peer IP address not specified.\n");
return -ENOEXEC;
}
if (capture_dev != NULL) {
PR_INFO("Capture already setup, cleaning up settings.\n");
net_capture_cleanup(capture_dev);
capture_dev = NULL;
}
ret = net_capture_setup(remote, local, peer, &capture_dev);
if (ret < 0) {
PR_WARNING("Capture cannot be setup (%d)\n", ret);
return -ENOEXEC;
}
PR_INFO("Capture setup done, next enable it by "
"\"net capture enable <idx>\"\n");
#else
ARG_UNUSED(argc);
ARG_UNUSED(argv);
PR_INFO("Set %s to enable %s support.\n",
"CONFIG_NET_CAPTURE", "network packet capture");
#endif
return 0;
}
static int cmd_net_capture_cleanup(const struct shell *shell, size_t argc,
char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_CAPTURE)
int ret;
if (capture_dev == NULL) {
return 0;
}
ret = net_capture_cleanup(capture_dev);
if (ret < 0) {
PR_WARNING("Capture %s failed (%d)\n", "cleanup", ret);
return -ENOEXEC;
}
capture_dev = NULL;
#else
PR_INFO("Set %s to enable %s support.\n",
"CONFIG_NET_CAPTURE", "network packet capture");
#endif
return 0;
}
static int cmd_net_capture_enable(const struct shell *shell, size_t argc,
char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_CAPTURE)
int ret, arg = 1, if_index;
struct net_if *iface;
if (capture_dev == NULL) {
return 0;
}
if (argv[arg] == NULL) {
PR_WARNING("Interface index is missing. Please give interface "
"what you want to monitor\n");
return -ENOEXEC;
}
if_index = atoi(argv[arg++]);
if (if_index == 0) {
PR_WARNING("Interface index %d is invalid.\n", if_index);
return -ENOEXEC;
}
iface = net_if_get_by_index(if_index);
if (iface == NULL) {
PR_WARNING("No such interface with index %d\n", if_index);
return -ENOEXEC;
}
ret = net_capture_enable(capture_dev, iface);
if (ret < 0) {
PR_WARNING("Capture %s failed (%d)\n", "enable", ret);
return -ENOEXEC;
}
#else
PR_INFO("Set %s to enable %s support.\n",
"CONFIG_NET_CAPTURE", "network packet capture");
#endif
return 0;
}
static int cmd_net_capture_disable(const struct shell *shell, size_t argc,
char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_CAPTURE)
int ret;
if (capture_dev == NULL) {
return 0;
}
ret = net_capture_disable(capture_dev);
if (ret < 0) {
PR_WARNING("Capture %s failed (%d)\n", "disable", ret);
return -ENOEXEC;
}
#else
PR_INFO("Set %s to enable %s support.\n",
"CONFIG_NET_CAPTURE", "network packet capture");
#endif
return 0;
}
static int cmd_net_conn(const struct shell *shell, 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.shell = shell;
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;
}
#if defined(CONFIG_DNS_RESOLVER)
static void dns_result_cb(enum dns_resolve_status status,
struct dns_addrinfo *info,
void *user_data)
{
const struct shell *shell = user_data;
if (status == DNS_EAI_CANCELED) {
PR_WARNING("dns: Timeout while resolving name.\n");
return;
}
if (status == DNS_EAI_INPROGRESS && info) {
char addr[NET_IPV6_ADDR_LEN];
if (info->ai_family == AF_INET) {
net_addr_ntop(AF_INET,
&net_sin(&info->ai_addr)->sin_addr,
addr, NET_IPV4_ADDR_LEN);
} else if (info->ai_family == AF_INET6) {
net_addr_ntop(AF_INET6,
&net_sin6(&info->ai_addr)->sin6_addr,
addr, NET_IPV6_ADDR_LEN);
} else {
strncpy(addr, "Invalid protocol family",
sizeof(addr));
/* strncpy() doesn't guarantee NUL byte at the end. */
addr[sizeof(addr) - 1] = 0;
}
PR("dns: %s\n", addr);
return;
}
if (status == DNS_EAI_ALLDONE) {
PR("dns: All results received\n");
return;
}
if (status == DNS_EAI_FAIL) {
PR_WARNING("dns: No such name found.\n");
return;
}
PR_WARNING("dns: Unhandled status %d received\n", status);
}
static void print_dns_info(const struct shell *shell,
struct dns_resolve_context *ctx)
{
int i;
PR("DNS servers:\n");
for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS +
DNS_MAX_MCAST_SERVERS; i++) {
if (ctx->servers[i].dns_server.sa_family == AF_INET) {
PR("\t%s:%u\n",
net_sprint_ipv4_addr(
&net_sin(&ctx->servers[i].dns_server)->
sin_addr),
ntohs(net_sin(
&ctx->servers[i].dns_server)->sin_port));
} else if (ctx->servers[i].dns_server.sa_family == AF_INET6) {
PR("\t[%s]:%u\n",
net_sprint_ipv6_addr(
&net_sin6(&ctx->servers[i].dns_server)->
sin6_addr),
ntohs(net_sin6(
&ctx->servers[i].dns_server)->sin6_port));
}
}
PR("Pending queries:\n");
for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
int32_t remaining;
if (!ctx->queries[i].cb || !ctx->queries[i].query) {
continue;
}
remaining = k_ticks_to_ms_ceil32(
k_work_delayable_remaining_get(&ctx->queries[i].timer));
if (ctx->queries[i].query_type == DNS_QUERY_TYPE_A) {
PR("\tIPv4[%u]: %s remaining %d\n",
ctx->queries[i].id,
ctx->queries[i].query,
remaining);
} else if (ctx->queries[i].query_type == DNS_QUERY_TYPE_AAAA) {
PR("\tIPv6[%u]: %s remaining %d\n",
ctx->queries[i].id,
ctx->queries[i].query,
remaining);
}
}
}
#endif
static int cmd_net_dns_cancel(const struct shell *shell, size_t argc,
char *argv[])
{
#if defined(CONFIG_DNS_RESOLVER)
struct dns_resolve_context *ctx;
int ret, i;
#endif
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_DNS_RESOLVER)
ctx = dns_resolve_get_default();
if (!ctx) {
PR_WARNING("No default DNS context found.\n");
return -ENOEXEC;
}
for (ret = 0, i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
if (!ctx->queries[i].cb) {
continue;
}
if (!dns_resolve_cancel(ctx, ctx->queries[i].id)) {
ret++;
}
}
if (ret) {
PR("Cancelled %d pending requests.\n", ret);
} else {
PR("No pending DNS requests.\n");
}
#else
PR_INFO("Set %s to enable %s support.\n", "CONFIG_DNS_RESOLVER",
"DNS resolver");
#endif
return 0;
}
static int cmd_net_dns_query(const struct shell *shell, size_t argc,
char *argv[])
{
#if defined(CONFIG_DNS_RESOLVER)
#define DNS_TIMEOUT (MSEC_PER_SEC * 2) /* ms */
enum dns_query_type qtype = DNS_QUERY_TYPE_A;
char *host, *type = NULL;
int ret, arg = 1;
host = argv[arg++];
if (!host) {
PR_WARNING("Hostname not specified.\n");
return -ENOEXEC;
}
if (argv[arg]) {
type = argv[arg];
}
if (type) {
if (strcmp(type, "A") == 0) {
qtype = DNS_QUERY_TYPE_A;
PR("IPv4 address type\n");
} else if (strcmp(type, "AAAA") == 0) {
qtype = DNS_QUERY_TYPE_AAAA;
PR("IPv6 address type\n");
} else {
PR_WARNING("Unknown query type, specify either "
"A or AAAA\n");
return -ENOEXEC;
}
}
ret = dns_get_addr_info(host, qtype, NULL, dns_result_cb,
(void *)shell, DNS_TIMEOUT);
if (ret < 0) {
PR_WARNING("Cannot resolve '%s' (%d)\n", host, ret);
} else {
PR("Query for '%s' sent.\n", host);
}
#else
PR_INFO("DNS resolver not supported. Set CONFIG_DNS_RESOLVER to "
"enable it.\n");
#endif
return 0;
}
static int cmd_net_dns(const struct shell *shell, size_t argc, char *argv[])
{
#if defined(CONFIG_DNS_RESOLVER)
struct dns_resolve_context *ctx;
#endif
#if defined(CONFIG_DNS_RESOLVER)
if (argv[1]) {
/* So this is a query then */
cmd_net_dns_query(shell, argc, argv);
return 0;
}
/* DNS status */
ctx = dns_resolve_get_default();
if (!ctx) {
PR_WARNING("No default DNS context found.\n");
return -ENOEXEC;
}
print_dns_info(shell, ctx);
#else
PR_INFO("DNS resolver not supported. Set CONFIG_DNS_RESOLVER to "
"enable it.\n");
#endif
return 0;
}
#if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
#define EVENT_MON_STACK_SIZE 1024
#define THREAD_PRIORITY K_PRIO_COOP(2)
#define MAX_EVENT_INFO_SIZE NET_EVENT_INFO_MAX_SIZE
#define MONITOR_L2_MASK (_NET_EVENT_IF_BASE)
#define MONITOR_L3_IPV4_MASK (_NET_EVENT_IPV4_BASE)
#define MONITOR_L3_IPV6_MASK (_NET_EVENT_IPV6_BASE)
#define MONITOR_L4_MASK (_NET_EVENT_L4_BASE)
static bool net_event_monitoring;
static bool net_event_shutting_down;
static struct net_mgmt_event_callback l2_cb;
static struct net_mgmt_event_callback l3_ipv4_cb;
static struct net_mgmt_event_callback l3_ipv6_cb;
static struct net_mgmt_event_callback l4_cb;
static struct k_thread event_mon;
static K_THREAD_STACK_DEFINE(event_mon_stack, EVENT_MON_STACK_SIZE);
struct event_msg {
struct net_if *iface;
size_t len;
uint32_t event;
uint8_t data[MAX_EVENT_INFO_SIZE];
};
K_MSGQ_DEFINE(event_mon_msgq, sizeof(struct event_msg),
CONFIG_NET_MGMT_EVENT_QUEUE_SIZE, sizeof(intptr_t));
static void event_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event, struct net_if *iface)
{
struct event_msg msg;
int ret;
memset(&msg, 0, sizeof(msg));
msg.len = MIN(sizeof(msg.data), cb->info_length);
msg.event = mgmt_event;
msg.iface = iface;
if (cb->info_length > 0) {
memcpy(msg.data, cb->info, msg.len);
}
ret = k_msgq_put(&event_mon_msgq, (void *)&msg, K_MSEC(10));
if (ret < 0) {
NET_ERR("Cannot write to msgq (%d)\n", ret);
}
}
static const char *get_l2_desc(uint32_t event)
{
static const char *desc = "<unknown event>";
switch (event) {
case NET_EVENT_IF_DOWN:
desc = "down";
break;
case NET_EVENT_IF_UP:
desc = "up";
break;
}
return desc;
}
static char *get_l3_desc(struct event_msg *msg,
const char **desc, const char **desc2,
char *extra_info, size_t extra_info_len)
{
static const char *desc_unknown = "<unknown event>";
char *info = NULL;
*desc = desc_unknown;
switch (msg->event) {
case NET_EVENT_IPV6_ADDR_ADD:
*desc = "IPv6 address";
*desc2 = "add";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_ADDR_DEL:
*desc = "IPv6 address";
*desc2 = "del";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_MADDR_ADD:
*desc = "IPv6 mcast address";
*desc2 = "add";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_MADDR_DEL:
*desc = "IPv6 mcast address";
*desc2 = "del";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_PREFIX_ADD:
*desc = "IPv6 prefix";
*desc2 = "add";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_PREFIX_DEL:
*desc = "IPv6 prefix";
*desc2 = "del";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_MCAST_JOIN:
*desc = "IPv6 mcast";
*desc2 = "join";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_MCAST_LEAVE:
*desc = "IPv6 mcast";
*desc2 = "leave";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_ROUTER_ADD:
*desc = "IPv6 router";
*desc2 = "add";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_ROUTER_DEL:
*desc = "IPv6 router";
*desc2 = "del";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_ROUTE_ADD:
*desc = "IPv6 route";
*desc2 = "add";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_ROUTE_DEL:
*desc = "IPv6 route";
*desc2 = "del";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_DAD_SUCCEED:
*desc = "IPv6 DAD";
*desc2 = "ok";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_DAD_FAILED:
*desc = "IPv6 DAD";
*desc2 = "fail";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_NBR_ADD:
*desc = "IPv6 neighbor";
*desc2 = "add";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV6_NBR_DEL:
*desc = "IPv6 neighbor";
*desc2 = "del";
info = net_addr_ntop(AF_INET6, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV4_ADDR_ADD:
*desc = "IPv4 address";
*desc2 = "add";
info = net_addr_ntop(AF_INET, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV4_ADDR_DEL:
*desc = "IPv4 address";
*desc2 = "del";
info = net_addr_ntop(AF_INET, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV4_ROUTER_ADD:
*desc = "IPv4 router";
*desc2 = "add";
info = net_addr_ntop(AF_INET, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV4_ROUTER_DEL:
*desc = "IPv4 router";
*desc2 = "del";
info = net_addr_ntop(AF_INET, msg->data, extra_info,
extra_info_len);
break;
case NET_EVENT_IPV4_DHCP_START:
*desc = "DHCPv4";
*desc2 = "start";
break;
case NET_EVENT_IPV4_DHCP_BOUND:
*desc = "DHCPv4";
*desc2 = "bound";
#if defined(CONFIG_NET_DHCPV4)
struct net_if_dhcpv4 *data = (struct net_if_dhcpv4 *)msg->data;
info = net_addr_ntop(AF_INET, &data->requested_ip, extra_info,
extra_info_len);
#endif
break;
case NET_EVENT_IPV4_DHCP_STOP:
*desc = "DHCPv4";
*desc2 = "stop";
break;
}
return info;
}
static const char *get_l4_desc(uint32_t event)
{
static const char *desc = "<unknown event>";
switch (event) {
case NET_EVENT_L4_CONNECTED:
desc = "connected";
break;
case NET_EVENT_L4_DISCONNECTED:
desc = "disconnected";
break;
case NET_EVENT_DNS_SERVER_ADD:
desc = "DNS server add";
break;
case NET_EVENT_DNS_SERVER_DEL:
desc = "DNS server del";
break;
}
return desc;
}
/* We use a separate thread in order not to do any shell printing from
* event handler callback (to avoid stack size issues).
*/
static void event_mon_handler(const struct shell *shell)
{
char extra_info[NET_IPV6_ADDR_LEN];
struct event_msg msg;
net_mgmt_init_event_callback(&l2_cb, event_handler,
MONITOR_L2_MASK);
net_mgmt_add_event_callback(&l2_cb);
net_mgmt_init_event_callback(&l3_ipv4_cb, event_handler,
MONITOR_L3_IPV4_MASK);
net_mgmt_add_event_callback(&l3_ipv4_cb);
net_mgmt_init_event_callback(&l3_ipv6_cb, event_handler,
MONITOR_L3_IPV6_MASK);
net_mgmt_add_event_callback(&l3_ipv6_cb);
net_mgmt_init_event_callback(&l4_cb, event_handler,
MONITOR_L4_MASK);
net_mgmt_add_event_callback(&l4_cb);
while (net_event_shutting_down == false) {
const char *layer_str = "<unknown layer>";
const char *desc = "", *desc2 = "";
char *info = NULL;
uint32_t layer;
(void)k_msgq_get(&event_mon_msgq, &msg, K_FOREVER);
if (msg.iface == NULL && msg.event == 0 && msg.len == 0) {
/* This is the stop message */
continue;
}
layer = NET_MGMT_GET_LAYER(msg.event);
if (layer == NET_MGMT_LAYER_L2) {
layer_str = "L2";
desc = get_l2_desc(msg.event);
} else if (layer == NET_MGMT_LAYER_L3) {
layer_str = "L3";
info = get_l3_desc(&msg, &desc, &desc2,
extra_info, NET_IPV6_ADDR_LEN);
} else if (layer == NET_MGMT_LAYER_L4) {
layer_str = "L4";
desc = get_l4_desc(msg.event);
}
PR_INFO("EVENT: %s [%d] %s%s%s%s%s\n", layer_str,
net_if_get_by_iface(msg.iface), desc,
desc2 ? " " : "", desc2 ? desc2 : "",
info ? " " : "", info ? info : "");
}
net_mgmt_del_event_callback(&l2_cb);
net_mgmt_del_event_callback(&l3_ipv4_cb);
net_mgmt_del_event_callback(&l3_ipv6_cb);
net_mgmt_del_event_callback(&l4_cb);
k_msgq_purge(&event_mon_msgq);
net_event_monitoring = false;
net_event_shutting_down = false;
PR_INFO("Network event monitoring %s.\n", "disabled");
}
#endif
static int cmd_net_events_on(const struct shell *shell, size_t argc,
char *argv[])
{
#if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
k_tid_t tid;
if (net_event_monitoring) {
PR_INFO("Network event monitoring is already %s.\n",
"enabled");
return -ENOEXEC;
}
tid = k_thread_create(&event_mon, event_mon_stack,
K_THREAD_STACK_SIZEOF(event_mon_stack),
(k_thread_entry_t)event_mon_handler,
(void *)shell, NULL, NULL, THREAD_PRIORITY, 0,
K_FOREVER);
if (!tid) {
PR_ERROR("Cannot create network event monitor thread!");
return -ENOEXEC;
}
k_thread_name_set(tid, "event_mon");
PR_INFO("Network event monitoring %s.\n", "enabled");
net_event_monitoring = true;
net_event_shutting_down = false;
k_thread_start(tid);
#else
PR_INFO("Network management events are not supported. "
"Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n");
#endif
return 0;
}
static int cmd_net_events_off(const struct shell *shell, size_t argc,
char *argv[])
{
#if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
static const struct event_msg msg;
int ret;
if (!net_event_monitoring) {
PR_INFO("Network event monitoring is already %s.\n",
"disabled");
return -ENOEXEC;
}
net_event_shutting_down = true;
ret = k_msgq_put(&event_mon_msgq, (void *)&msg, K_MSEC(100));
if (ret < 0) {
PR_ERROR("Cannot write to msgq (%d)\n", ret);
return -ENOEXEC;
}
#else
PR_INFO("Network management events are not supported. "
"Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n");
#endif
return 0;
}
static int cmd_net_events(const struct shell *shell, size_t argc, char *argv[])
{
#if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
PR("Network event monitoring is %s.\n",
net_event_monitoring ? "enabled" : "disabled");
if (!argv[1]) {
PR_INFO("Give 'on' to enable event monitoring and "
"'off' to disable it.\n");
}
#else
PR_INFO("Network management events are not supported. "
"Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n");
#endif
return 0;
}
#if defined(CONFIG_NET_GPTP)
static const char *selected_role_str(int port);
static void gptp_port_cb(int port, struct net_if *iface, void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *shell = data->shell;
int *count = data->user_data;
if (*count == 0) {
PR("Port Interface \tRole\n");
}
(*count)++;
PR("%2d %p [%d] \t%s\n", port, iface, net_if_get_by_iface(iface),
selected_role_str(port));
}
static const char *pdelay_req2str(enum gptp_pdelay_req_states state)
{
switch (state) {
case GPTP_PDELAY_REQ_NOT_ENABLED:
return "REQ_NOT_ENABLED";
case GPTP_PDELAY_REQ_INITIAL_SEND_REQ:
return "INITIAL_SEND_REQ";
case GPTP_PDELAY_REQ_RESET:
return "REQ_RESET";
case GPTP_PDELAY_REQ_SEND_REQ:
return "SEND_REQ";
case GPTP_PDELAY_REQ_WAIT_RESP:
return "WAIT_RESP";
case GPTP_PDELAY_REQ_WAIT_FOLLOW_UP:
return "WAIT_FOLLOW_UP";
case GPTP_PDELAY_REQ_WAIT_ITV_TIMER:
return "WAIT_ITV_TIMER";
}
return "<unknown>";
};
static const char *pdelay_resp2str(enum gptp_pdelay_resp_states state)
{
switch (state) {
case GPTP_PDELAY_RESP_NOT_ENABLED:
return "RESP_NOT_ENABLED";
case GPTP_PDELAY_RESP_INITIAL_WAIT_REQ:
return "INITIAL_WAIT_REQ";
case GPTP_PDELAY_RESP_WAIT_REQ:
return "WAIT_REQ";
case GPTP_PDELAY_RESP_WAIT_TSTAMP:
return "WAIT_TSTAMP";
}
return "<unknown>";
}
static const char *sync_rcv2str(enum gptp_sync_rcv_states state)
{
switch (state) {
case GPTP_SYNC_RCV_DISCARD:
return "DISCARD";
case GPTP_SYNC_RCV_WAIT_SYNC:
return "WAIT_SYNC";
case GPTP_SYNC_RCV_WAIT_FOLLOW_UP:
return "WAIT_FOLLOW_UP";
}
return "<unknown>";
}
static const char *sync_send2str(enum gptp_sync_send_states state)
{
switch (state) {
case GPTP_SYNC_SEND_INITIALIZING:
return "INITIALIZING";
case GPTP_SYNC_SEND_SEND_SYNC:
return "SEND_SYNC";
case GPTP_SYNC_SEND_SEND_FUP:
return "SEND_FUP";
}
return "<unknown>";
}
static const char *pss_rcv2str(enum gptp_pss_rcv_states state)
{
switch (state) {
case GPTP_PSS_RCV_DISCARD:
return "DISCARD";
case GPTP_PSS_RCV_RECEIVED_SYNC:
return "RECEIVED_SYNC";
}
return "<unknown>";
}
static const char *pss_send2str(enum gptp_pss_send_states state)
{
switch (state) {
case GPTP_PSS_SEND_TRANSMIT_INIT:
return "TRANSMIT_INIT";
case GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT:
return "SYNC_RECEIPT_TIMEOUT";
case GPTP_PSS_SEND_SEND_MD_SYNC:
return "SEND_MD_SYNC";
case GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT:
return "SET_SYNC_RECEIPT_TIMEOUT";
}
return "<unknown>";
}
static const char *pa_rcv2str(enum gptp_pa_rcv_states state)
{
switch (state) {
case GPTP_PA_RCV_DISCARD:
return "DISCARD";
case GPTP_PA_RCV_RECEIVE:
return "RECEIVE";
}
return "<unknown>";
};
static const char *pa_info2str(enum gptp_pa_info_states state)
{
switch (state) {
case GPTP_PA_INFO_DISABLED:
return "DISABLED";
case GPTP_PA_INFO_POST_DISABLED:
return "POST_DISABLED";
case GPTP_PA_INFO_AGED:
return "AGED";
case GPTP_PA_INFO_UPDATE:
return "UPDATE";
case GPTP_PA_INFO_CURRENT:
return "CURRENT";
case GPTP_PA_INFO_RECEIVE:
return "RECEIVE";
case GPTP_PA_INFO_SUPERIOR_MASTER_PORT:
return "SUPERIOR_MASTER_PORT";
case GPTP_PA_INFO_REPEATED_MASTER_PORT:
return "REPEATED_MASTER_PORT";
case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT:
return "INFERIOR_MASTER_OR_OTHER_PORT";
}
return "<unknown>";
};
static const char *pa_transmit2str(enum gptp_pa_transmit_states state)
{
switch (state) {
case GPTP_PA_TRANSMIT_INIT:
return "INIT";
case GPTP_PA_TRANSMIT_PERIODIC:
return "PERIODIC";
case GPTP_PA_TRANSMIT_IDLE:
return "IDLE";
case GPTP_PA_TRANSMIT_POST_IDLE:
return "POST_IDLE";
}
return "<unknown>";
};
static const char *site_sync2str(enum gptp_site_sync_sync_states state)
{
switch (state) {
case GPTP_SSS_INITIALIZING:
return "INITIALIZING";
case GPTP_SSS_RECEIVING_SYNC:
return "RECEIVING_SYNC";
}
return "<unknown>";
}
static const char *clk_slave2str(enum gptp_clk_slave_sync_states state)
{
switch (state) {
case GPTP_CLK_SLAVE_SYNC_INITIALIZING:
return "INITIALIZING";
case GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND:
return "SEND_SYNC_IND";
}
return "<unknown>";
};
static const char *pr_selection2str(enum gptp_pr_selection_states state)
{
switch (state) {
case GPTP_PR_SELECTION_INIT_BRIDGE:
return "INIT_BRIDGE";
case GPTP_PR_SELECTION_ROLE_SELECTION:
return "ROLE_SELECTION";
}
return "<unknown>";
};
static const char *cms_rcv2str(enum gptp_cms_rcv_states state)
{
switch (state) {
case GPTP_CMS_RCV_INITIALIZING:
return "INITIALIZING";
case GPTP_CMS_RCV_WAITING:
return "WAITING";
case GPTP_CMS_RCV_SOURCE_TIME:
return "SOURCE_TIME";
}
return "<unknown>";
};
#if !defined(USCALED_NS_TO_NS)
#define USCALED_NS_TO_NS(val) (val >> 16)
#endif
static const char *selected_role_str(int port)
{
switch (GPTP_GLOBAL_DS()->selected_role[port]) {
case GPTP_PORT_INITIALIZING:
return "INITIALIZING";
case GPTP_PORT_FAULTY:
return "FAULTY";
case GPTP_PORT_DISABLED:
return "DISABLED";
case GPTP_PORT_LISTENING:
return "LISTENING";
case GPTP_PORT_PRE_MASTER:
return "PRE-MASTER";
case GPTP_PORT_MASTER:
return "MASTER";
case GPTP_PORT_PASSIVE:
return "PASSIVE";
case GPTP_PORT_UNCALIBRATED:
return "UNCALIBRATED";
case GPTP_PORT_SLAVE:
return "SLAVE";
}
return "<unknown>";
}
static void gptp_print_port_info(const struct shell *shell, int port)
{
struct gptp_port_bmca_data *port_bmca_data;
struct gptp_port_param_ds *port_param_ds;
struct gptp_port_states *port_state;
struct gptp_domain *gptp_domain;
struct gptp_port_ds *port_ds;
struct net_if *iface;
int ret, i;
gptp_domain = gptp_get_domain();
ret = gptp_get_port_data(gptp_domain,
port,
&port_ds,
&port_param_ds,
&port_state,
&port_bmca_data,
&iface);
if (ret < 0) {
PR_WARNING("Cannot get gPTP information for port %d (%d)\n",
port, ret);
return;
}
NET_ASSERT(port == port_ds->port_id.port_number,
"Port number mismatch! (%d vs %d)", port,
port_ds->port_id.port_number);
PR("Port id : %d (%s)\n", port_ds->port_id.port_number,
selected_role_str(port_ds->port_id.port_number));
PR("Interface : %p [%d]\n", iface, net_if_get_by_iface(iface));
PR("Clock id : ");
for (i = 0; i < sizeof(port_ds->port_id.clk_id); i++) {
PR("%02x", port_ds->port_id.clk_id[i]);
if (i != (sizeof(port_ds->port_id.clk_id) - 1)) {
PR(":");
}
}
PR("\n");
PR("Version : %d\n", port_ds->version);
PR("AS capable : %s\n", port_ds->as_capable ? "yes" : "no");
PR("\nConfiguration:\n");
PR("Time synchronization and Best Master Selection enabled "
": %s\n", port_ds->ptt_port_enabled ? "yes" : "no");
PR("The port is measuring the path delay "
": %s\n", port_ds->is_measuring_delay ? "yes" : "no");
PR("One way propagation time on %s : %u ns\n",
"the link attached to this port",
(uint32_t)port_ds->neighbor_prop_delay);
PR("Propagation time threshold for %s : %u ns\n",
"the link attached to this port",
(uint32_t)port_ds->neighbor_prop_delay_thresh);
PR("Estimate of the ratio of the frequency with the peer "
": %u\n", (uint32_t)port_ds->neighbor_rate_ratio);
PR("Asymmetry on the link relative to the grand master time base "
": %" PRId64 "\n", port_ds->delay_asymmetry);
PR("Maximum interval between sync %s "
": %" PRIu64 "\n", "messages",
port_ds->sync_receipt_timeout_time_itv);
PR("Maximum number of Path Delay Requests without a response "
": %d\n", port_ds->allowed_lost_responses);
PR("Current Sync %s : %d\n",
"sequence id for this port", port_ds->sync_seq_id);
PR("Current Path Delay Request %s : %d\n",
"sequence id for this port", port_ds->pdelay_req_seq_id);
PR("Current Announce %s : %d\n",
"sequence id for this port", port_ds->announce_seq_id);
PR("Current Signaling %s : %d\n",
"sequence id for this port", port_ds->signaling_seq_id);
PR("Whether neighborRateRatio %s : %s\n",
"needs to be computed for this port",
port_ds->compute_neighbor_rate_ratio ? "yes" : "no");
PR("Whether neighborPropDelay %s : %s\n",
"needs to be computed for this port",
port_ds->compute_neighbor_prop_delay ? "yes" : "no");
PR("Initial Announce Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->ini_log_announce_itv);
PR("Current Announce Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->cur_log_announce_itv);
PR("Initial Sync Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->ini_log_half_sync_itv);
PR("Current Sync Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->cur_log_half_sync_itv);
PR("Initial Path Delay Request Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->ini_log_pdelay_req_itv);
PR("Current Path Delay Request Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->cur_log_pdelay_req_itv);
PR("Time without receiving announce %s %s : %d ms (%d)\n",
"messages", "before running BMCA",
gptp_uscaled_ns_to_timer_ms(
&port_bmca_data->ann_rcpt_timeout_time_interval),
port_ds->announce_receipt_timeout);
PR("Time without receiving sync %s %s : %" PRIu64 " ms (%d)\n",
"messages", "before running BMCA",
(port_ds->sync_receipt_timeout_time_itv >> 16) /
(NSEC_PER_SEC / MSEC_PER_SEC),
port_ds->sync_receipt_timeout);
PR("Sync event %s : %" PRIu64 " ms\n",
"transmission interval for the port",
USCALED_NS_TO_NS(port_ds->half_sync_itv.low) /
(NSEC_PER_USEC * USEC_PER_MSEC));
PR("Path Delay Request %s : %" PRIu64 " ms\n",
"transmission interval for the port",
USCALED_NS_TO_NS(port_ds->pdelay_req_itv.low) /
(NSEC_PER_USEC * USEC_PER_MSEC));
PR("BMCA %s %s%d%s: %d\n", "default", "priority", 1,
" ",
gptp_domain->default_ds.priority1);
PR("BMCA %s %s%d%s: %d\n", "default", "priority", 2,
" ",
gptp_domain->default_ds.priority2);
PR("\nRuntime status:\n");
PR("Current global port state "
" : %s\n", selected_role_str(port));
PR("Path Delay Request state machine variables:\n");
PR("\tCurrent state "
": %s\n", pdelay_req2str(port_state->pdelay_req.state));
PR("\tInitial Path Delay Response Peer Timestamp "
": %" PRIu64 "\n", port_state->pdelay_req.ini_resp_evt_tstamp);
PR("\tInitial Path Delay Response Ingress Timestamp "
": %" PRIu64 "\n", port_state->pdelay_req.ini_resp_ingress_tstamp);
PR("\tPath Delay Response %s %s : %u\n",
"messages", "received",
port_state->pdelay_req.rcvd_pdelay_resp);
PR("\tPath Delay Follow Up %s %s : %u\n",
"messages", "received",
port_state->pdelay_req.rcvd_pdelay_follow_up);
PR("\tNumber of lost Path Delay Responses "
": %u\n", port_state->pdelay_req.lost_responses);
PR("\tTimer expired send a new Path Delay Request "
": %u\n", port_state