zephyr/subsys/net/ip/net_shell.c
Jukka Rissanen 2ff503b7c8 net: shell: Check strtol() conversion errors
Make sure that string to integer conversions are checked properly
so that we are not trying to use the return value from strtol()
if the string is not a number.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
2018-08-06 14:21:26 +03:00

3696 lines
95 KiB
C

/** @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.h>
#include <stdlib.h>
#include <stdio.h>
#include <shell/shell.h>
#include <net/net_if.h>
#include <net/dns_resolve.h>
#include <misc/printk.h>
#include "route.h"
#include "icmpv6.h"
#include "icmpv4.h"
#include "connection.h"
#if defined(CONFIG_NET_TCP)
#include <net/tcp.h>
#include "tcp_internal.h"
#endif
#if defined(CONFIG_NET_IPV6)
#include "ipv6.h"
#endif
#if defined(CONFIG_HTTP)
#include <net/http.h>
#endif
#if defined(CONFIG_NET_APP)
#include <net/net_app.h>
#endif
#if defined(CONFIG_NET_RPL)
#include "rpl.h"
#endif
#if defined(CONFIG_NET_ARP)
#include "ethernet/arp.h"
#endif
#if defined(CONFIG_NET_L2_ETHERNET)
#include <net/ethernet.h>
#endif
#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
#include <net/ethernet_mgmt.h>
#endif
#if defined(CONFIG_NET_GPTP)
#include <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
#include "net_shell.h"
#include "net_stats.h"
/*
* Set NET_LOG_ENABLED in order to activate address printing functions
* in net_private.h
*/
#define NET_LOG_ENABLED 1
#include "net_private.h"
#define NET_SHELL_MODULE "net"
/* net_stack dedicated section limiters */
extern struct net_stack_info __net_stack_start[];
extern struct net_stack_info __net_stack_end[];
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_DUMMY
if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
if (extra) {
*extra = "=====";
}
return "Dummy";
}
#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
if (extra) {
*extra = "==============";
}
return "<unknown type>";
}
#if defined(CONFIG_NET_L2_ETHERNET)
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_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_PROMISC_MODE, "Promiscuous mode"),
EC(ETHERNET_PRIORITY_QUEUES, "Priority queues"),
EC(ETHERNET_HW_FILTERING, "MAC address filtering"),
};
static void print_supported_ethernet_capabilities(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) {
printk("\t%s\n", eth_hw_caps[i].description);
}
}
}
#endif /* CONFIG_NET_L2_ETHERNET */
static void iface_cb(struct net_if *iface, void *user_data)
{
#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
struct net_if_addr *unicast;
struct net_if_mcast_addr *mcast;
#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
struct ethernet_req_params params;
int ret;
#endif
const char *extra;
int i, count;
ARG_UNUSED(user_data);
printk("\nInterface %p (%s) [%d]\n", iface, iface2str(iface, &extra),
net_if_get_by_iface(iface));
printk("===========================%s\n", extra);
if (!net_if_is_up(iface)) {
printk("Interface is down.\n");
return;
}
if (net_if_get_link_addr(iface) &&
net_if_get_link_addr(iface)->addr) {
printk("Link addr : %s\n",
net_sprint_ll_addr(net_if_get_link_addr(iface)->addr,
net_if_get_link_addr(iface)->len));
}
printk("MTU : %d\n", net_if_get_mtu(iface));
#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
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;
printk("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));
printk("\t%d: Qav ", i);
if (ret) {
printk("not supported\n");
} else {
printk("%s\n",
params.qav_param.enabled ?
"enabled" :
"disabled");
}
}
}
#endif
#if defined(CONFIG_NET_PROMISCUOUS_MODE)
printk("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;
}
printk("VLAN tag : %d (0x%x)\n",
eth_ctx->vlan[i].tag,
eth_ctx->vlan[i].tag);
}
} else {
printk("VLAN not enabled\n");
}
}
#endif
#ifdef CONFIG_NET_L2_ETHERNET
if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
printk("Ethernet capabilities supported:\n");
print_supported_ethernet_capabilities(iface);
}
#endif /* CONFIG_NET_L2_ETHERNET */
#if defined(CONFIG_NET_IPV6)
count = 0;
ipv6 = iface->config.ip.ipv6;
printk("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;
}
printk("\t%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" : "");
count++;
}
if (count == 0) {
printk("\t<none>\n");
}
count = 0;
printk("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;
}
printk("\t%s\n",
net_sprint_ipv6_addr(&mcast->address.in6_addr));
count++;
}
if (count == 0) {
printk("\t<none>\n");
}
count = 0;
printk("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;
}
printk("\t%s/%d%s\n",
net_sprint_ipv6_addr(&prefix->prefix),
prefix->len,
prefix->is_infinite ? " infinite" : "");
count++;
}
if (count == 0) {
printk("\t<none>\n");
}
router = net_if_ipv6_router_find_default(iface, NULL);
if (router) {
printk("IPv6 default router :\n");
printk("\t%s%s\n",
net_sprint_ipv6_addr(&router->address.in6_addr),
router->is_infinite ? " infinite" : "");
}
if (ipv6) {
printk("IPv6 hop limit : %d\n",
ipv6->hop_limit);
printk("IPv6 base reachable time : %d\n",
ipv6->base_reachable_time);
printk("IPv6 reachable time : %d\n",
ipv6->reachable_time);
printk("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) {
printk("IPv4 not supported for this interface.\n");
return;
}
count = 0;
ipv4 = iface->config.ip.ipv4;
printk("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;
}
printk("\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) {
printk("\t<none>\n");
}
count = 0;
printk("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;
}
printk("\t%s\n",
net_sprint_ipv4_addr(&mcast->address.in_addr));
count++;
}
if (count == 0) {
printk("\t<none>\n");
}
if (ipv4) {
printk("IPv4 gateway : %s\n",
net_sprint_ipv4_addr(&ipv4->gw));
printk("IPv4 netmask : %s\n",
net_sprint_ipv4_addr(&ipv4->netmask));
}
#endif /* CONFIG_NET_IPV4 */
#if defined(CONFIG_NET_DHCPV4)
printk("DHCPv4 lease time : %u\n",
iface->config.dhcpv4.lease_time);
printk("DHCPv4 renew time : %u\n",
iface->config.dhcpv4.renewal_time);
printk("DHCPv4 server : %s\n",
net_sprint_ipv4_addr(&iface->config.dhcpv4.server_id));
printk("DHCPv4 requested : %s\n",
net_sprint_ipv4_addr(&iface->config.dhcpv4.requested_ip));
printk("DHCPv4 state : %s\n",
net_dhcpv4_state_name(iface->config.dhcpv4.state));
printk("DHCPv4 attempts : %d\n",
iface->config.dhcpv4.attempts);
#endif /* CONFIG_NET_DHCPV4 */
}
#if defined(CONFIG_NET_ROUTE)
static void route_cb(struct net_route_entry *entry, void *user_data)
{
struct net_if *iface = user_data;
struct net_route_nexthop *nexthop_route;
int count;
if (entry->iface != iface) {
return;
}
printk("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;
if (!nexthop_route->nbr) {
continue;
}
printk("\tneighbor : %p\t", nexthop_route->nbr);
if (nexthop_route->nbr->idx == NET_NBR_LLADDR_UNKNOWN) {
printk("addr : <unknown>\n");
} else {
lladdr = net_nbr_get_lladdr(nexthop_route->nbr->idx);
printk("addr : %s\n",
net_sprint_ll_addr(lladdr->addr,
lladdr->len));
}
count++;
}
if (count == 0) {
printk("\t<none>\n");
}
}
static void iface_per_route_cb(struct net_if *iface, void *user_data)
{
const char *extra;
ARG_UNUSED(user_data);
printk("\nIPv6 routes for interface %p (%s)\n", iface,
iface2str(iface, &extra));
printk("=======================================%s\n", extra);
net_route_foreach(route_cb, iface);
}
#endif /* CONFIG_NET_ROUTE */
#if defined(CONFIG_NET_ROUTE_MCAST)
static void route_mcast_cb(struct net_route_entry_mcast *entry,
void *user_data)
{
struct net_if *iface = user_data;
const char *extra;
if (entry->iface != iface) {
return;
}
printk("IPv6 multicast route %p for interface %p (%s)\n", entry,
iface, iface2str(iface, &extra));
printk("==========================================================="
"%s\n", extra);
printk("IPv6 group : %s\n", net_sprint_ipv6_addr(&entry->group));
printk("Lifetime : %u\n", entry->lifetime);
}
static void iface_per_mcast_route_cb(struct net_if *iface, void *user_data)
{
net_route_mcast_foreach(route_mcast_cb, NULL, iface);
}
#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)
{
printk("Statistics for Ethernet interface %p [%d]\n", iface,
net_if_get_by_iface(iface));
printk("Bytes received : %u\n", data->bytes.received);
printk("Bytes sent : %u\n", data->bytes.sent);
printk("Packets received : %u\n", data->pkts.rx);
printk("Packets sent : %u\n", data->pkts.tx);
printk("Bcast received : %u\n", data->broadcast.rx);
printk("Bcast sent : %u\n", data->broadcast.tx);
printk("Mcast received : %u\n", data->multicast.rx);
printk("Mcast sent : %u\n", data->multicast.tx);
#if defined(CONFIG_NET_STATISTICS_ETHERNET_VENDOR)
if (data->vendor) {
printk("Vendor specific statistics for Ethernet interface %p [%d]:\n",
iface, net_if_get_by_iface(iface));
size_t i = 0;
do {
printk("%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 */
static void net_shell_print_statistics(struct net_if *iface, void *user_data)
{
ARG_UNUSED(user_data);
if (iface) {
const char *extra;
printk("\nInterface %p (%s) [%d]\n", iface,
iface2str(iface, &extra),
net_if_get_by_iface(iface));
printk("===========================%s\n", extra);
} else {
printk("\nGlobal statistics\n");
printk("=================\n");
}
#if defined(CONFIG_NET_IPV6)
printk("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_IPV6_ND)
printk("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_IPV6_ND */
#if defined(CONFIG_NET_STATISTICS_MLD)
printk("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_IPV6 */
#if defined(CONFIG_NET_IPV4)
printk("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_IPV4 */
printk("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));
printk("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));
printk("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));
printk("ICMP typeer %d\tchkerr\t%d\n",
GET_STAT(iface, icmp.typeerr),
GET_STAT(iface, icmp.chkerr));
#if defined(CONFIG_NET_UDP)
printk("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));
printk("UDP chkerr %d\n",
GET_STAT(iface, udp.chkerr));
#endif
#if defined(CONFIG_NET_STATISTICS_TCP)
printk("TCP bytes recv %u\tsent\t%d\n",
GET_STAT(iface, tcp.bytes.received),
GET_STAT(iface, tcp.bytes.sent));
printk("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.drop));
printk("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n",
GET_STAT(iface, tcp.resent),
GET_STAT(iface, tcp.chkerr),
GET_STAT(iface, tcp.ackerr));
printk("TCP seg rsterr %d\trst\t%d\tre-xmit\t%d\n",
GET_STAT(iface, tcp.rsterr),
GET_STAT(iface, tcp.rst),
GET_STAT(iface, tcp.rexmit));
printk("TCP conn drop %d\tconnrst\t%d\n",
GET_STAT(iface, tcp.conndrop),
GET_STAT(iface, tcp.connrst));
#endif
#if defined(CONFIG_NET_STATISTICS_RPL)
printk("RPL DIS recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(iface, rpl.dis.recv),
GET_STAT(iface, rpl.dis.sent),
GET_STAT(iface, rpl.dis.drop));
printk("RPL DIO recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(iface, rpl.dio.recv),
GET_STAT(iface, rpl.dio.sent),
GET_STAT(iface, rpl.dio.drop));
printk("RPL DAO recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
GET_STAT(iface, rpl.dao.recv),
GET_STAT(iface, rpl.dao.sent),
GET_STAT(iface, rpl.dao.drop),
GET_STAT(iface, rpl.dao.forwarded));
printk("RPL DAOACK rcv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(iface, rpl.dao_ack.recv),
GET_STAT(iface, rpl.dao_ack.sent),
GET_STAT(iface, rpl.dao_ack.drop));
printk("RPL overflows %d\tl-repairs\t%d\tg-repairs\t%d\n",
GET_STAT(iface, rpl.mem_overflows),
GET_STAT(iface, rpl.local_repairs),
GET_STAT(iface, rpl.global_repairs));
printk("RPL malformed %d\tresets \t%d\tp-switch\t%d\n",
GET_STAT(iface, rpl.malformed_msgs),
GET_STAT(iface, rpl.resets),
GET_STAT(iface, rpl.parent_switch));
printk("RPL f-errors %d\tl-errors\t%d\tl-warnings\t%d\n",
GET_STAT(iface, rpl.forward_errors),
GET_STAT(iface, rpl.loop_errors),
GET_STAT(iface, rpl.loop_warnings));
printk("RPL r-repairs %d\n",
GET_STAT(iface, rpl.root_repairs));
#endif
printk("Bytes received %u\n", GET_STAT(iface, bytes.received));
printk("Bytes sent %u\n", GET_STAT(iface, bytes.sent));
printk("Processing err %d\n", GET_STAT(iface, processing_error));
#if NET_TC_COUNT > 1
{
int i;
#if NET_TC_TX_COUNT > 1
printk("TX traffic class statistics:\n");
printk("TC Priority\tSent pkts\tbytes\n");
for (i = 0; i < NET_TC_TX_COUNT; i++) {
printk("[%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
#if NET_TC_RX_COUNT > 1
printk("RX traffic class statistics:\n");
printk("TC Priority\tRecv pkts\tbytes\n");
for (i = 0; i < NET_TC_RX_COUNT; i++) {
printk("[%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
#endif /* NET_TC_COUNT > 1 */
#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);
}
}
#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */
}
#endif /* CONFIG_NET_STATISTICS */
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 {
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
int *count = 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));
printk("[%2d] %p\t%p %c%c%c %16s\t%16s\n",
(*count) + 1, context,
net_context_get_iface(context),
net_context_get_family(context) == AF_INET6 ? '6' : '4',
net_context_get_type(context) == SOCK_DGRAM ? 'D' : 'S',
net_context_get_ip_proto(context) == IPPROTO_UDP ?
'U' : 'T',
addr_local, addr_remote);
(*count)++;
}
#if defined(CONFIG_NET_DEBUG_CONN)
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
int *count = 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);
}
printk("[%2d] %p %p\t%s\t%16s\t%16s\n",
(*count) + 1, conn, conn->cb, net_proto2str(conn->proto),
addr_local, addr_remote);
(*count)++;
}
#endif /* CONFIG_NET_DEBUG_CONN */
#if defined(CONFIG_NET_TCP)
static void tcp_cb(struct net_tcp *tcp, void *user_data)
{
int *count = user_data;
u16_t recv_mss = net_tcp_get_recv_mss(tcp);
printk("%p %p %5u %5u %10u %10u %5u %s\n",
tcp, tcp->context,
ntohs(net_sin6_ptr(&tcp->context->local)->sin6_port),
ntohs(net_sin6(&tcp->context->remote)->sin6_port),
tcp->send_seq, tcp->send_ack, recv_mss,
net_tcp_state_str(net_tcp_get_state(tcp)));
(*count)++;
}
#if defined(CONFIG_NET_DEBUG_TCP)
static void tcp_sent_list_cb(struct net_tcp *tcp, void *user_data)
{
int *printed = user_data;
struct net_pkt *pkt;
struct net_pkt *tmp;
if (sys_slist_is_empty(&tcp->sent_list)) {
return;
}
if (!*printed) {
printk("\nTCP packets waiting ACK:\n");
printk("TCP net_pkt[ref/totlen]->net_buf[ref/len]...\n");
}
printk("%p ", tcp);
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp->sent_list, pkt, tmp,
sent_list) {
struct net_buf *frag = pkt->frags;
if (!*printed) {
printk("%p[%d/%zd]", pkt, pkt->ref,
net_pkt_get_len(pkt));
*printed = true;
} else {
printk(" %p[%d/%zd]", pkt, pkt->ref,
net_pkt_get_len(pkt));
}
if (frag) {
printk("->");
}
while (frag) {
printk("%p[%d/%d]", frag, frag->ref, frag->len);
frag = frag->frags;
if (frag) {
printk("->");
}
}
printk("\n");
}
*printed = true;
}
#endif /* CONFIG_NET_DEBUG_TCP */
#endif
#if defined(CONFIG_NET_IPV6_FRAGMENT)
static void ipv6_frag_cb(struct net_ipv6_reassembly *reass,
void *user_data)
{
int *count = user_data;
char src[ADDR_LEN];
int i;
if (!*count) {
printk("\nIPv6 reassembly Id Remain Src \tDst\n");
}
snprintk(src, ADDR_LEN, "%s", net_sprint_ipv6_addr(&reass->src));
printk("%p 0x%08x %5d %16s\t%16s\n",
reass, reass->id, k_delayed_work_remaining_get(&reass->timer),
src, net_sprint_ipv6_addr(&reass->dst));
for (i = 0; i < NET_IPV6_FRAGMENTS_MAX_PKT; i++) {
if (reass->pkt[i]) {
struct net_buf *frag = reass->pkt[i]->frags;
printk("[%d] pkt %p->", i, reass->pkt[i]);
while (frag) {
printk("%p", frag);
frag = frag->frags;
if (frag) {
printk("->");
}
}
printk("\n");
}
}
(*count)++;
}
#endif /* CONFIG_NET_IPV6_FRAGMENT */
#if defined(CONFIG_NET_DEBUG_NET_PKT)
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)
{
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) {
printk("%p/%d\t%5s\t%5s\t%s():%d\n", pkt, pkt->ref,
str, net_pkt_slab2str(pkt->slab), func_alloc,
line_alloc);
} else {
printk("%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) {
printk("%p/%d\t%5s\t%5s\t%s():%d\n", buf, buf->ref,
str, net_pkt_pool2str(pool), func_alloc,
line_alloc);
} else {
printk("%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 */
/* Put the actual shell commands after this */
int net_shell_cmd_allocs(int argc, char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_DEBUG_NET_PKT)
printk("Network memory allocations\n\n");
printk("memory\t\tStatus\tPool\tFunction alloc -> freed\n");
net_pkt_allocs_foreach(allocs_cb, NULL);
#else
printk("Enable CONFIG_NET_DEBUG_NET_PKT to see allocations.\n");
#endif /* CONFIG_NET_DEBUG_NET_PKT */
return 0;
}
#if defined(CONFIG_NET_DEBUG_APP) && \
(defined(CONFIG_NET_APP_SERVER) || defined(CONFIG_NET_APP_CLIENT))
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
static void print_app_sec_info(struct net_app_ctx *ctx, const char *sec_type)
{
printk(" Security: %s Thread id: %p\n", sec_type, ctx->tls.tid);
#if defined(CONFIG_INIT_STACKS)
{
unsigned int pcnt, unused;
net_analyze_stack_get_values(
K_THREAD_STACK_BUFFER(ctx->tls.stack),
ctx->tls.stack_size,
&pcnt, &unused);
printk(" Stack: %p Size: %d bytes unused %u usage "
"%u/%d (%u %%)\n",
ctx->tls.stack, ctx->tls.stack_size,
unused, ctx->tls.stack_size - unused,
ctx->tls.stack_size, pcnt);
}
#endif /* CONFIG_INIT_STACKS */
if (ctx->tls.cert_host) {
printk(" Cert host: %s\n", ctx->tls.cert_host);
}
}
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
static void net_app_cb(struct net_app_ctx *ctx, void *user_data)
{
int *count = user_data;
char *sec_type = "none";
char *app_type = "unknown";
char *proto = "unknown";
bool printed = false;
#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
/* +7 for []:port */
char addr_local[ADDR_LEN + 7];
char addr_remote[ADDR_LEN + 7] = "";
if (*count == 0) {
if (ctx->app_type == NET_APP_SERVER) {
printk("Network application server instances\n\n");
} else if (ctx->app_type == NET_APP_CLIENT) {
printk("Network application client instances\n\n");
} else {
printk("Invalid network application type %d\n",
ctx->app_type);
}
}
if (IS_ENABLED(CONFIG_NET_APP_TLS) && ctx->is_tls) {
if (ctx->sock_type == SOCK_STREAM) {
sec_type = "TLS";
}
}
if (IS_ENABLED(CONFIG_NET_APP_DTLS) && ctx->is_tls) {
if (ctx->sock_type == SOCK_DGRAM) {
sec_type = "DTLS";
}
}
if (ctx->app_type == NET_APP_SERVER) {
app_type = "server";
} else if (ctx->app_type == NET_APP_CLIENT) {
app_type = "client";
}
if (ctx->proto == IPPROTO_UDP) {
#if defined(CONFIG_NET_UDP)
proto = "UDP";
#else
proto = "<UDP not configured>";
#endif
}
if (ctx->proto == IPPROTO_TCP) {
#if defined(CONFIG_NET_TCP)
proto = "TCP";
#else
proto = "<TCP not configured>";
#endif
}
printk("[%2d] App-ctx: %p Status: %s Type: %s Protocol: %s\n",
*count, ctx, ctx->is_enabled ? "enabled" : "disabled",
app_type, proto);
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
if (ctx->is_tls) {
print_app_sec_info(ctx, sec_type);
}
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
#if defined(CONFIG_NET_IPV6)
if (ctx->app_type == NET_APP_SERVER) {
if (ctx->ipv6.ctx && ctx->ipv6.ctx->local.family == AF_INET6) {
get_addresses(ctx->ipv6.ctx,
addr_local, sizeof(addr_local),
addr_remote, sizeof(addr_remote));
printk(" Listen IPv6: %16s <- %16s\n",
addr_local, addr_remote);
} else {
printk(" Not listening IPv6 connections.\n");
}
} else if (ctx->app_type == NET_APP_CLIENT) {
if (ctx->ipv6.ctx && ctx->ipv6.ctx->local.family == AF_INET6) {
get_addresses(ctx->ipv6.ctx,
addr_local, sizeof(addr_local),
addr_remote, sizeof(addr_remote));
printk(" Connect IPv6: %16s -> %16s\n",
addr_local, addr_remote);
}
} else {
printk("Invalid application type %d\n", ctx->app_type);
printed = true;
}
#else
printk(" IPv6 connections not enabled.\n");
#endif
#if defined(CONFIG_NET_IPV4)
if (ctx->app_type == NET_APP_SERVER) {
if (ctx->ipv4.ctx && ctx->ipv4.ctx->local.family == AF_INET) {
get_addresses(ctx->ipv4.ctx,
addr_local, sizeof(addr_local),
addr_remote, sizeof(addr_remote));
printk(" Listen IPv4: %16s <- %16s\n",
addr_local, addr_remote);
} else {
printk(" Not listening IPv4 connections.\n");
}
} else if (ctx->app_type == NET_APP_CLIENT) {
if (ctx->ipv4.ctx && ctx->ipv4.ctx->local.family == AF_INET) {
get_addresses(ctx->ipv4.ctx,
addr_local, sizeof(addr_local),
addr_remote, sizeof(addr_remote));
printk(" Connect IPv4: %16s -> %16s\n",
addr_local, addr_remote);
}
} else {
if (!printed) {
printk("Invalid application type %d\n", ctx->app_type);
}
}
#else
printk(" IPv4 connections not enabled.\n");
#endif
#if defined(CONFIG_NET_APP_SERVER)
#if defined(CONFIG_NET_TCP)
{
int i, found = 0;
for (i = 0; i < CONFIG_NET_APP_SERVER_NUM_CONN; i++) {
if (!ctx->server.net_ctxs[i] ||
!net_context_is_used(ctx->server.net_ctxs[i])) {
continue;
}
get_addresses(ctx->server.net_ctxs[i],
addr_local, sizeof(addr_local),
addr_remote, sizeof(addr_remote));
printk(" Active: %16s <- %16s\n",
addr_local, addr_remote);
found++;
}
if (!found) {
printk(" No active connections to this server.\n");
}
}
#else
printk(" TCP not enabled for this server.\n");
#endif
#endif /* CONFIG_NET_APP_SERVER */
(*count)++;
return;
}
#elif defined(CONFIG_NET_DEBUG_APP)
static void net_app_cb(struct net_app_ctx *ctx, void *user_data) {}
#endif
int net_shell_cmd_app(int argc, char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_DEBUG_APP)
int i = 0;
if (IS_ENABLED(CONFIG_NET_APP_SERVER)) {
net_app_server_foreach(net_app_cb, &i);
if (i == 0) {
printk("No net app server instances found.\n");
i = -1;
}
}
if (IS_ENABLED(CONFIG_NET_APP_CLIENT)) {
if (i) {
printk("\n");
i = 0;
}
net_app_client_foreach(net_app_cb, &i);
if (i == 0) {
printk("No net app client instances found.\n");
}
}
#else
printk("Enable CONFIG_NET_DEBUG_APP and either CONFIG_NET_APP_CLIENT "
"or CONFIG_NET_APP_SERVER to see client/server instance "
"information.\n");
#endif
return 0;
}
#if defined(CONFIG_NET_ARP)
static void arp_cb(struct arp_entry *entry, void *user_data)
{
int *count = user_data;
if (*count == 0) {
printk(" Interface Link Address\n");
}
printk("[%2d] %p %s %s\n", *count, 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 */
int net_shell_cmd_arp(int argc, char *argv[])
{
ARG_UNUSED(argc);
#if defined(CONFIG_NET_ARP)
int arg = 1;
if (!argv[arg]) {
/* ARP cache content */
int count = 0;
if (net_arp_foreach(arp_cb, &count) == 0) {
printk("ARP cache is empty.\n");
}
return 0;
}
if (strcmp(argv[arg], "flush") == 0) {
printk("Flushing ARP cache.\n");
net_arp_clear_cache(NULL);
return 0;
}
#else
printk("Enable CONFIG_NET_ARP, CONFIG_NET_IPV4 and "
"CONFIG_NET_L2_ETHERNET to see ARP information.\n");
#endif
return 0;
}
int net_shell_cmd_conn(int argc, char *argv[])
{
int count = 0;
ARG_UNUSED(argc);
ARG_UNUSED(argv);
printk(" Context \tIface Flags "
"Local \tRemote\n");
net_context_foreach(context_cb, &count);
if (count == 0) {
printk("No connections\n");
}
#if defined(CONFIG_NET_DEBUG_CONN)
printk("\n Handler Callback \tProto\t"
"Local \tRemote\n");
count = 0;
net_conn_foreach(conn_handler_cb, &count);
if (count == 0) {
printk("No connection handlers found.\n");
}
#endif
#if defined(CONFIG_NET_TCP)
printk("\nTCP Context Src port Dst port Send-Seq Send-Ack MSS"
" State\n");
count = 0;
net_tcp_foreach(tcp_cb, &count);
if (count == 0) {
printk("No TCP connections\n");
} else {
#if defined(CONFIG_NET_DEBUG_TCP)
/* Print information about pending packets */
count = 0;
net_tcp_foreach(tcp_sent_list_cb, &count);
#endif /* CONFIG_NET_DEBUG_TCP */
}
#if !defined(CONFIG_NET_DEBUG_TCP)
printk("\nEnable CONFIG_NET_DEBUG_TCP for additional info\n");
#endif /* CONFIG_NET_DEBUG_TCP */
#endif
#if defined(CONFIG_NET_IPV6_FRAGMENT)
count = 0;
net_ipv6_frag_foreach(ipv6_frag_cb, &count);
/* Do not print anything if no fragments are pending atm */
#endif
return 0;
}
#if defined(CONFIG_DNS_RESOLVER)
static void dns_result_cb(enum dns_resolve_status status,
struct dns_addrinfo *info,
void *user_data)
{
bool *first = user_data;
if (status == DNS_EAI_CANCELED) {
printk("\nTimeout while resolving name.\n");
*first = false;
return;
}
if (status == DNS_EAI_INPROGRESS && info) {
char addr[NET_IPV6_ADDR_LEN];
if (*first) {
printk("\n");
*first = false;
}
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));
}
printk("\t%s\n", addr);
return;
}
if (status == DNS_EAI_ALLDONE) {
printk("All results received\n");
*first = false;
return;
}
if (status == DNS_EAI_FAIL) {
printk("No such name found.\n");
*first = false;
return;
}
printk("Unhandled status %d received\n", status);
}
static void print_dns_info(struct dns_resolve_context *ctx)
{
int i;
printk("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) {
printk("\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) {
printk("\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));
}
}
printk("Pending queries:\n");
for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
s32_t remaining;
if (!ctx->queries[i].cb) {
continue;
}
remaining =
k_delayed_work_remaining_get(&ctx->queries[i].timer);
if (ctx->queries[i].query_type == DNS_QUERY_TYPE_A) {
printk("\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) {
printk("\tIPv6[%u]: %s remaining %d\n",
ctx->queries[i].id,
ctx->queries[i].query,
remaining);
}
}
}
#endif
int net_shell_cmd_dns(int argc, char *argv[])
{
#if defined(CONFIG_DNS_RESOLVER)
#define DNS_TIMEOUT K_MSEC(2000) /* ms */
struct dns_resolve_context *ctx;
enum dns_query_type qtype = DNS_QUERY_TYPE_A;
char *host, *type = NULL;
bool first = true;
int arg = 1;
int ret, i;
if (!argv[arg]) {
/* DNS status */
ctx = dns_resolve_get_default();
if (!ctx) {
printk("No default DNS context found.\n");
return 0;
}
print_dns_info(ctx);
return 0;
}
if (strcmp(argv[arg], "cancel") == 0) {
ctx = dns_resolve_get_default();
if (!ctx) {
printk("No default DNS context found.\n");
return 0;
}
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) {
printk("Cancelled %d pending requests.\n", ret);
} else {
printk("No pending DNS requests.\n");
}
return 0;
}
host = argv[arg++];
if (argv[arg]) {
type = argv[arg];
}
if (type) {
if (strcmp(type, "A") == 0) {
qtype = DNS_QUERY_TYPE_A;
printk("IPv4 address type\n");
} else if (strcmp(type, "AAAA") == 0) {
qtype = DNS_QUERY_TYPE_AAAA;
printk("IPv6 address type\n");
} else {
printk("Unknown query type, specify either "
"A or AAAA\n");
return 0;
}
}
ret = dns_get_addr_info(host, qtype, NULL, dns_result_cb, &first,
DNS_TIMEOUT);
if (ret < 0) {
printk("Cannot resolve '%s' (%d)\n", host, ret);
} else {
printk("Query for '%s' sent.\n", host);
}
#else
printk("DNS resolver not supported.\n");
#endif
return 0;
}
#if defined(CONFIG_NET_GPTP)
static void gptp_port_cb(int port, struct net_if *iface, void *user_data)
{
int *count = user_data;
if (*count == 0) {
printk("Port Interface\n");
}
(*count)++;
printk("%2d %p\n", port, iface);
}
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(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_port_ds *port_ds;
struct net_if *iface;
int ret, i;
ret = gptp_get_port_data(gptp_get_domain(),
port,
&port_ds,
&port_param_ds,
&port_state,
&port_bmca_data,
&iface);
if (ret < 0) {
printk("Cannot get gPTP information for port %d (%d)\n",
port, ret);
return;
}
printk("Port id : %d\n", port_ds->port_id.port_number);
printk("Clock id : ");
for (i = 0; i < sizeof(port_ds->port_id.clk_id); i++) {
printk("%02x", port_ds->port_id.clk_id[i]);
if (i != (sizeof(port_ds->port_id.clk_id) - 1)) {
printk(":");
}
}
printk("\n");
printk("Version : %d\n", port_ds->version);
printk("AS capable : %s\n", port_ds->as_capable ? "yes" : "no");
printk("\nConfiguration:\n");
printk("Time synchronization and Best Master Selection enabled "
": %s\n", port_ds->ptt_port_enabled ? "yes" : "no");
printk("The port is measuring the path delay "
": %s\n", port_ds->is_measuring_delay ? "yes" : "no");
printf("One way propagation time on %s : %u ns\n",
"the link attached to this port",
(u32_t)port_ds->neighbor_prop_delay);
printf("Propagation time threshold for %s : %u ns\n",
"the link attached to this port",
(u32_t)port_ds->neighbor_prop_delay_thresh);
printk("Estimate of the ratio of the frequency with the peer "
": %u\n", (u32_t)port_ds->neighbor_rate_ratio);
printk("Asymmetry on the link relative to the grand master time base "
": %lld\n", port_ds->delay_asymmetry);
printk("Maximum interval between sync %s "
": %llu\n", "messages", port_ds->sync_receipt_timeout_time_itv);
printk("Maximum number of Path Delay Requests without a response "
": %d\n", port_ds->allowed_lost_responses);
printk("Current Sync %s : %d\n",
"sequence id for this port", port_ds->sync_seq_id);
printk("Current Path Delay Request %s : %d\n",
"sequence id for this port", port_ds->pdelay_req_seq_id);
printk("Current Announce %s : %d\n",
"sequence id for this port", port_ds->announce_seq_id);
printk("Current Signaling %s : %d\n",
"sequence id for this port", port_ds->signaling_seq_id);
printk("Whether neighborRateRatio %s : %s\n",
"needs to be computed for this port",
port_ds->compute_neighbor_rate_ratio ? "yes" : "no");
printk("Whether neighborPropDelay %s : %s\n",
"needs to be computed for this port",
port_ds->compute_neighbor_prop_delay ? "yes" : "no");
printk("Initial Announce Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->ini_log_announce_itv);
printk("Current Announce Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->cur_log_announce_itv);
printk("Initial Sync Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->ini_log_half_sync_itv);
printk("Current Sync Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->cur_log_half_sync_itv);
printk("Initial Path Delay Request Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->ini_log_pdelay_req_itv);
printk("Current Path Delay Request Interval %s : %d\n",
"as a Logarithm to base 2", port_ds->cur_log_pdelay_req_itv);
printk("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);
printk("Time without receiving sync %s %s : %llu 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);
printk("Sync event %s : %llu ms\n",
"transmission interval for the port",
USCALED_NS_TO_NS(port_ds->half_sync_itv.low) /
(NSEC_PER_USEC * USEC_PER_MSEC));
printk("Path Delay Request %s : %llu ms\n",
"transmission interval for the port",
USCALED_NS_TO_NS(port_ds->pdelay_req_itv.low) /
(NSEC_PER_USEC * USEC_PER_MSEC));
printk("\nRuntime status:\n");
printk("Current global port state "
" : %s\n", selected_role_str(port));
printk("Path Delay Request state machine variables:\n");
printk("\tCurrent state "
": %s\n", pdelay_req2str(port_state->pdelay_req.state));
printk("\tInitial Path Delay Response Peer Timestamp "
": %llu\n", port_state->pdelay_req.ini_resp_evt_tstamp);
printk("\tInitial Path Delay Response Ingress Timestamp "
": %llu\n", port_state->pdelay_req.ini_resp_ingress_tstamp);
printk("\tPath Delay Response %s %s : %u\n",
"messages", "received",
port_state->pdelay_req.rcvd_pdelay_resp);
printk("\tPath Delay Follow Up %s %s : %u\n",
"messages", "received",
port_state->pdelay_req.rcvd_pdelay_follow_up);
printk("\tNumber of lost Path Delay Responses "
": %u\n", port_state->pdelay_req.lost_responses);
printk("\tTimer expired send a new Path Delay Request "
": %u\n", port_state->pdelay_req.pdelay_timer_expired);
printk("\tNeighborRateRatio has been computed successfully "
": %u\n", port_state->pdelay_req.neighbor_rate_ratio_valid);
printk("\tPath Delay has already been computed after init "
": %u\n", port_state->pdelay_req.init_pdelay_compute);
printk("\tCount consecutive reqs with multiple responses "
": %u\n", port_state->pdelay_req.multiple_resp_count);
printk("Path Delay Response state machine variables:\n");
printk("\tCurrent state "
": %s\n", pdelay_resp2str(port_state->pdelay_resp.state));
printk("SyncReceive state machine variables:\n");
printk("\tCurrent state "
": %s\n", sync_rcv2str(port_state->sync_rcv.state));
printk("\tA Sync %s %s : %s\n",
"Message", "has been received",
port_state->sync_rcv.rcvd_sync ? "yes" : "no");
printk("\tA Follow Up %s %s : %s\n",
"Message", "has been received",
port_state->sync_rcv.rcvd_follow_up ? "yes" : "no");
printk("\tA Follow Up %s %s : %s\n",
"Message", "timeout",
port_state->sync_rcv.follow_up_timeout_expired ? "yes" : "no");
printk("\tTime at which a Sync %s without Follow Up\n"
"\t will be discarded "
": %llu\n", "Message",
port_state->sync_rcv.follow_up_receipt_timeout);
printk("SyncSend state machine variables:\n");
printk("\tCurrent state "
": %s\n", sync_send2str(port_state->sync_send.state));
printk("\tA MDSyncSend structure %s : %s\n",
"has been received",
port_state->sync_send.rcvd_md_sync ? "yes" : "no");
printk("\tThe timestamp for the sync msg %s : %s\n",
"has been received",
port_state->sync_send.md_sync_timestamp_avail ? "yes" : "no");
printk("PortSyncSyncReceive state machine variables:\n");
printk("\tCurrent state "
": %s\n", pss_rcv2str(port_state->pss_rcv.state));
printf("\tGrand Master / Local Clock frequency ratio "
": %f\n", port_state->pss_rcv.rate_ratio);
printk("\tA MDSyncReceive struct is ready to be processed "
": %s\n", port_state->pss_rcv.rcvd_md_sync ? "yes" : "no");
printk("\tExpiry of SyncReceiptTimeoutTimer : %s\n",
port_state->pss_rcv.rcv_sync_receipt_timeout_timer_expired ?
"yes" : "no");
printk("PortSyncSyncSend state machine variables:\n");
printk("\tCurrent state "
": %s\n", pss_send2str(port_state->pss_send.state));
printk("\tFollow Up Correction Field of last recv PSS "
": %lld\n",
port_state->pss_send.last_follow_up_correction_field);
printk("\tUpstream Tx Time of the last recv PortSyncSync "
": %llu\n", port_state->pss_send.last_upstream_tx_time);
printk("\tSync Receipt Timeout Time of last recv PSS "
": %llu\n",
port_state->pss_send.last_sync_receipt_timeout_time);
printf("\tRate Ratio of the last received PortSyncSync "
": %f\n",
port_state->pss_send.last_rate_ratio);
printf("\tGM Freq Change of the last received PortSyncSync "
": %f\n", port_state->pss_send.last_gm_freq_change);
printk("\tGM Time Base Indicator of last recv PortSyncSync "
": %d\n", port_state->pss_send.last_gm_time_base_indicator);
printk("\tReceived Port Number of last recv PortSyncSync "
": %d\n",
port_state->pss_send.last_rcvd_port_num);
printk("\tPortSyncSync structure is ready to be processed "
": %s\n", port_state->pss_send.rcvd_pss_sync ? "yes" : "no");
printk("\tFlag when the %s has expired : %s\n",
"half_sync_itv_timer",
port_state->pss_send.half_sync_itv_timer_expired ?
"yes" : "no");
printk("\tHas %s expired twice : %s\n",
"half_sync_itv_timer",
port_state->pss_send.sync_itv_timer_expired ? "yes" : "no");
printk("\tHas syncReceiptTimeoutTime expired "
": %s\n",
port_state->pss_send.send_sync_receipt_timeout_timer_expired ?
"yes" : "no");
printk("PortAnnounceReceive state machine variables:\n");
printk("\tCurrent state "
": %s\n", pa_rcv2str(port_state->pa_rcv.state));
printk("\tAn announce message is ready to be processed "
": %s\n",
port_state->pa_rcv.rcvd_announce ? "yes" : "no");
printk("PortAnnounceInformation state machine variables:\n");
printk("\tCurrent state "
": %s\n", pa_info2str(port_state->pa_info.state));
printk("\tExpired announce information "
": %s\n", port_state->pa_info.ann_expired ? "yes" : "no");
printk("PortAnnounceTransmit state machine variables:\n");
printk("\tCurrent state "
": %s\n", pa_transmit2str(port_state->pa_transmit.state));
printk("\tTrigger announce information "
": %s\n", port_state->pa_transmit.ann_trigger ? "yes" : "no");
#if defined(CONFIG_NET_GPTP_STATISTICS)
printk("\nStatistics:\n");
printk("Sync %s %s : %u\n",
"messages", "received", port_param_ds->rx_sync_count);
printk("Follow Up %s %s : %u\n",
"messages", "received", port_param_ds->rx_fup_count);
printk("Path Delay Request %s %s : %u\n",
"messages", "received", port_param_ds->rx_pdelay_req_count);
printk("Path Delay Response %s %s : %u\n",
"messages", "received", port_param_ds->rx_pdelay_resp_count);
printk("Path Delay %s threshold %s : %u\n",
"messages", "exceeded",
port_param_ds->neighbor_prop_delay_exceeded);
printk("Path Delay Follow Up %s %s : %u\n",
"messages", "received", port_param_ds->rx_pdelay_resp_fup_count);
printk("Announce %s %s : %u\n",
"messages", "received", port_param_ds->rx_announce_count);
printk("ptp %s discarded : %u\n",
"messages", port_param_ds->rx_ptp_packet_discard_count);
printk("Sync %s %s : %u\n",
"reception", "timeout",
port_param_ds->sync_receipt_timeout_count);
printk("Announce %s %s : %u\n",
"reception", "timeout",
port_param_ds->announce_receipt_timeout_count);
printk("Path Delay Requests without a response "
": %u\n", port_param_ds->pdelay_allowed_lost_resp_exceed_count);
printk("Sync %s %s : %u\n",
"messages", "sent", port_param_ds->tx_sync_count);
printk("Follow Up %s %s : %u\n",
"messages", "sent", port_param_ds->tx_fup_count);
printk("Path Delay Request %s %s : %u\n",
"messages", "sent", port_param_ds->tx_pdelay_req_count);
printk("Path Delay Response %s %s : %u\n",
"messages", "sent", port_param_ds->tx_pdelay_resp_count);
printk("Path Delay Response FUP %s %s : %u\n",
"messages", "sent", port_param_ds->tx_pdelay_resp_fup_count);
printk("Announce %s %s : %u\n",
"messages", "sent", port_param_ds->tx_announce_count);
#endif /* CONFIG_NET_GPTP_STATISTICS */
}
#endif /* CONFIG_NET_GPTP */
int net_shell_cmd_gptp(int argc, char *argv[])
{
#if defined(CONFIG_NET_GPTP)
/* gPTP status */
struct gptp_domain *domain = gptp_get_domain();
int count = 0;
int arg = 1;
if (strcmp(argv[0], "gptp")) {
arg++;
}
if (argv[arg]) {
char *endptr;
int port = strtol(argv[arg], &endptr, 10);
if (*endptr == '\0') {
gptp_print_port_info(port);
} else {
printk("Not a valid gPTP port number: %s\n", argv[arg]);
}
} else {
gptp_foreach_port(gptp_port_cb, &count);
printk("\n");
printk("SiteSyncSync state machine variables:\n");
printk("\tCurrent state "
": %s\n", site_sync2str(domain->state.site_ss.state));
printk("\tA PortSyncSync struct is ready "
": %s\n", domain->state.site_ss.rcvd_pss ? "yes" : "no");
printk("ClockSlaveSync state machine variables:\n");
printk("\tCurrent state "
": %s\n",
clk_slave2str(domain->state.clk_slave_sync.state));
printk("\tA PortSyncSync struct is ready "
": %s\n",
domain->state.clk_slave_sync.rcvd_pss ? "yes" : "no");
printk("\tThe local clock has expired "
": %s\n",
domain->state.clk_slave_sync.rcvd_local_clk_tick ?
"yes" : "no");
printk("PortRoleSelection state machine variables:\n");
printk("\tCurrent state "
": %s\n",
pr_selection2str(domain->state.pr_sel.state));
printk("ClockMasterSyncReceive state machine variables:\n");
printk("\tCurrent state "
": %s\n", cms_rcv2str(
domain->state.clk_master_sync_receive.state));
printk("\tA ClockSourceTime "
": %s\n",
domain->state.clk_master_sync_receive.rcvd_clock_source_req ?
"yes" : "no");
printk("\tThe local clock has expired "
": %s\n",
domain->state.clk_master_sync_receive.rcvd_local_clock_tick ?
"yes" : "no");
}
#else
printk("gPTP not supported, set CONFIG_NET_GPTP to enable it.\n");
#endif
return 0;
}
#if defined(CONFIG_NET_DEBUG_HTTP_CONN) && defined(CONFIG_HTTP_SERVER)
#define MAX_HTTP_OUTPUT_LEN 64
static char *http_str_output(char *output, int outlen, const char *str, int len)
{
if (len > outlen) {
len = outlen;
}
if (len == 0) {
memset(output, 0, outlen);
} else {
memcpy(output, str, len);
output[len] = '\0';
}
return output;
}
static void http_server_cb(struct http_ctx *entry, void *user_data)
{
int *count = user_data;
static char output[MAX_HTTP_OUTPUT_LEN];
int i;
/* +7 for []:port */
char addr_local[ADDR_LEN + 7];
char addr_remote[ADDR_LEN + 7] = "";
if (*count == 0) {
printk(" HTTP ctx Local \t"
"Remote \tURL\n");
}
(*count)++;
for (i = 0; i < CONFIG_NET_APP_SERVER_NUM_CONN; i++) {
if (!entry->app_ctx.server.net_ctxs[i] ||
!net_context_is_used(entry->app_ctx.server.net_ctxs[i])) {
continue;
}
get_addresses(entry->app_ctx.server.net_ctxs[i],
addr_local, sizeof(addr_local),
addr_remote, sizeof(addr_remote));
printk("[%2d] %c%c %p %16s\t%16s\t%s\n",
*count,
entry->app_ctx.is_enabled ? 'E' : 'D',
entry->is_tls ? 'S' : ' ',
entry, addr_local, addr_remote,
http_str_output(output, sizeof(output) - 1,
entry->http.url, entry->http.url_len));
}
}
#endif /* CONFIG_NET_DEBUG_HTTP_CONN && CONFIG_HTTP_SERVER */
int net_shell_cmd_http(int argc, char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_DEBUG_HTTP_CONN) && defined(CONFIG_HTTP_SERVER)
static int count;
int arg = 1;
count = 0;
/* Turn off monitoring if it was enabled */
http_server_conn_monitor(NULL, NULL);
if (strcmp(argv[0], "http")) {
arg++;
}
if (argv[arg]) {
if (strcmp(argv[arg], "monitor") == 0) {
printk("Activating HTTP monitor. Type \"net http\" "
"to disable HTTP connection monitoring.\n");
http_server_conn_monitor(http_server_cb, &count);
}
} else {
http_server_conn_foreach(http_server_cb, &count);
}
#else
printk("Enable CONFIG_NET_DEBUG_HTTP_CONN and CONFIG_HTTP_SERVER "
"to get HTTP server connection information\n");
#endif
return 0;
}
int net_shell_cmd_iface(int argc, char *argv[])
{
int arg = 0;
bool up = false;
char *endptr;
struct net_if *iface;
int idx, ret;
if (strcmp(argv[arg], "iface") == 0) {
arg++;
}
if (!argv[arg]) {
#if defined(CONFIG_NET_HOSTNAME_ENABLE)
printk("Hostname: %s\n\n", net_hostname_get());
#endif
net_if_foreach(iface_cb, NULL);
return 0;
}
if (strcmp(argv[arg], "up") == 0) {
arg++;
up = true;
} else if (strcmp(argv[arg], "down") == 0) {
arg++;
}
if (!argv[arg]) {
printk("Usage: net iface [up|down] [index]\n");
return 0;
}
idx = strtol(argv[arg], &endptr, 10);
if (*endptr != '\0') {
printk("Invalid index %s\n", argv[arg]);
return 0;
}
if (idx < 0 || idx > 255) {
printk("Invalid index %d\n", idx);
return 0;
}
iface = net_if_get_by_index(idx);
if (!iface) {
printk("No such interface in index %d\n", idx);
return 0;
}
if (up) {
if (net_if_is_up(iface)) {
printk("Interface %d is already up.\n", idx);
return 0;
}
ret = net_if_up(iface);
if (ret) {
printk("Cannot take interface %d up (%d)\n",
idx, ret);
} else {
printk("Interface %d is up\n", idx);
}
} else {
ret = net_if_down(iface);
if (ret) {
printk("Cannot take interface %d down (%d)\n",
idx, ret);
} else {
printk("Interface %d is down\n", idx);
}
}
return 0;
}
struct ctx_info {
int pos;
bool are_external_pools;
struct k_mem_slab *tx_slabs[CONFIG_NET_MAX_CONTEXTS];
struct net_buf_pool *data_pools[CONFIG_NET_MAX_CONTEXTS];
};
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
static bool slab_pool_found_already(struct ctx_info *info,
struct k_mem_slab *slab,
struct net_buf_pool *pool)
{
int i;
for (i = 0; i < CONFIG_NET_MAX_CONTEXTS; i++) {
if (slab) {
if (info->tx_slabs[i] == slab) {
return true;
}
} else {
if (info->data_pools[i] == pool) {
return true;
}
}
}
return false;
}
#endif
static void context_info(struct net_context *context, void *user_data)
{
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
struct ctx_info *info = user_data;
struct k_mem_slab *slab;
struct net_buf_pool *pool;
if (!net_context_is_used(context)) {
return;
}
if (context->tx_slab) {
slab = context->tx_slab();
if (slab_pool_found_already(info, slab, NULL)) {
return;
}
#if defined(CONFIG_NET_DEBUG_NET_PKT)
printk("%p\t%u\t%u\tETX\n",
slab, slab->num_blocks, k_mem_slab_num_free_get(slab));
#else
printk("%p\t%d\tETX\n", slab, slab->num_blocks);
#endif
info->are_external_pools = true;
info->tx_slabs[info->pos] = slab;
}
if (context->data_pool) {
pool = context->data_pool();
if (slab_pool_found_already(info, NULL, pool)) {
return;
}
#if defined(CONFIG_NET_DEBUG_NET_PKT)
printk("%p\t%d\t%d\tEDATA (%s)\n",
pool, pool->buf_count,
pool->avail_count, pool->name);
#else
printk("%p\t%d\tEDATA\n", pool, pool->buf_count);
#endif
info->are_external_pools = true;
info->data_pools[info->pos] = pool;
}
info->pos++;
#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
}
int net_shell_cmd_mem(int argc, char *argv[])
{
struct k_mem_slab *rx, *tx;
struct net_buf_pool *rx_data, *tx_data;
ARG_UNUSED(argc);
ARG_UNUSED(argv);
net_pkt_get_info(&rx, &tx, &rx_data, &tx_data);
printk("Fragment length %d bytes\n", CONFIG_NET_BUF_DATA_SIZE);
printk("Network buffer pools:\n");
#if defined(CONFIG_NET_BUF_POOL_USAGE)
printk("Address\t\tTotal\tAvail\tName\n");
printk("%p\t%d\t%u\tRX\n",
rx, rx->num_blocks, k_mem_slab_num_free_get(rx));
printk("%p\t%d\t%u\tTX\n",
tx, tx->num_blocks, k_mem_slab_num_free_get(tx));
printk("%p\t%d\t%d\tRX DATA (%s)\n",
rx_data, rx_data->buf_count,
rx_data->avail_count, rx_data->name);
printk("%p\t%d\t%d\tTX DATA (%s)\n",
tx_data, tx_data->buf_count,
tx_data->avail_count, tx_data->name);
#else
printk("(CONFIG_NET_BUF_POOL_USAGE to see free #s)\n");
printk("Address\t\tTotal\tName\n");
printk("%p\t%d\tRX\n", rx, rx->num_blocks);
printk("%p\t%d\tTX\n", tx, tx->num_blocks);
printk("%p\t%d\tRX DATA\n", rx_data, rx_data->buf_count);
printk("%p\t%d\tTX DATA\n", tx_data, tx_data->buf_count);
#endif /* CONFIG_NET_BUF_POOL_USAGE */
if (IS_ENABLED(CONFIG_NET_CONTEXT_NET_PKT_POOL)) {
struct ctx_info info;
memset(&info, 0, sizeof(info));
net_context_foreach(context_info, &info);
if (!info.are_external_pools) {
printk("No external memory pools found.\n");
}
}
return 0;
}
#if defined(CONFIG_NET_IPV6)
static void nbr_cb(struct net_nbr *nbr, void *user_data)
{
int *count = user_data;
char *padding = "";
char *state_pad = "";
const char *state_str;
#if defined(CONFIG_NET_L2_IEEE802154)
padding = " ";
#endif
if (*count == 0) {
printk(" Neighbor Interface Flags State "
"Remain Link %sAddress\n", padding);
}
(*count)++;
state_str = net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state);
/* This is not a proper way but the minimal libc does not honor
* string lengths in %s modifier so in order the output to look
* nice, do it like this.
*/
if (strlen(state_str) == 5) {
state_pad = " ";
}
printk("[%2d] %p %p %5d/%d/%d/%d %s%s %6d %17s%s %s\n",
*count, nbr, nbr->iface,
net_ipv6_nbr_data(nbr)->link_metric,
nbr->ref,
net_ipv6_nbr_data(nbr)->ns_count,
net_ipv6_nbr_data(nbr)->is_router,
state_str,
state_pad,
#if defined(CONFIG_NET_IPV6_ND)
k_delayed_work_remaining_get(
&net_ipv6_nbr_data(nbr)->reachable),
#else
0,
#endif
nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "?" :
net_sprint_ll_addr(
net_nbr_get_lladdr(nbr->idx)->addr,
net_nbr_get_lladdr(nbr->idx)->len),
net_nbr_get_lladdr(nbr->idx)->len == 8 ? "" : padding,
net_sprint_ipv6_addr(&net_ipv6_nbr_data(nbr)->addr));
}
#endif
int net_shell_cmd_nbr(int argc, char *argv[])
{
#if defined(CONFIG_NET_IPV6)
int count = 0;
int arg = 1;
if (argv[arg]) {
struct in6_addr addr;
int ret;
if (strcmp(argv[arg], "rm")) {
printk("Unknown command '%s'\n", argv[arg]);
return 0;
}
if (!argv[++arg]) {
printk("Neighbor IPv6 address missing.\n");
return 0;
}
ret = net_addr_pton(AF_INET6, argv[arg], &addr);
if (ret < 0) {
printk("Cannot parse '%s'\n", argv[arg]);
return 0;
}
if (!net_ipv6_nbr_rm(NULL, &addr)) {
printk("Cannot remove neighbor %s\n",
net_sprint_ipv6_addr(&addr));
} else {
printk("Neighbor %s removed.\n",
net_sprint_ipv6_addr(&addr));
}
}
net_ipv6_nbr_foreach(nbr_cb, &count);
if (count == 0) {
printk("No neighbors.\n");
}
#else
printk("IPv6 not enabled.\n");
#endif /* CONFIG_NET_IPV6 */
return 0;
}
#if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_IPV4)
K_SEM_DEFINE(ping_timeout, 0, 1);
#if defined(CONFIG_NET_IPV6)
static enum net_verdict _handle_ipv6_echo_reply(struct net_pkt *pkt);
static struct net_icmpv6_handler ping6_handler = {
.type = NET_ICMPV6_ECHO_REPLY,
.code = 0,
.handler = _handle_ipv6_echo_reply,
};
static inline void _remove_ipv6_ping_handler(void)
{
net_icmpv6_unregister_handler(&ping6_handler);
}
static enum net_verdict _handle_ipv6_echo_reply(struct net_pkt *pkt)
{
char addr[NET_IPV6_ADDR_LEN];
snprintk(addr, sizeof(addr), "%s",
net_sprint_ipv6_addr(&NET_IPV6_HDR(pkt)->dst));
printk("Received echo reply from %s to %s\n",
net_sprint_ipv6_addr(&NET_IPV6_HDR(pkt)->src), addr);
k_sem_give(&ping_timeout);
_remove_ipv6_ping_handler();
net_pkt_unref(pkt);
return NET_OK;
}
static int _ping_ipv6(char *host)
{
struct in6_addr ipv6_target;
struct net_if *iface = net_if_get_default();
struct net_nbr *nbr;
int ret;
#if defined(CONFIG_NET_ROUTE)
struct net_route_entry *route;
#endif
if (net_addr_pton(AF_INET6, host, &ipv6_target) < 0) {
return -EINVAL;
}
net_icmpv6_register_handler(&ping6_handler);
nbr = net_ipv6_nbr_lookup(NULL, &ipv6_target);
if (nbr) {
iface = nbr->iface;
}
#if defined(CONFIG_NET_ROUTE)
route = net_route_lookup(NULL, &ipv6_target);
if (route) {
iface = route->iface;
}
#endif
ret = net_icmpv6_send_echo_request(iface,
&ipv6_target,
sys_rand32_get(),
sys_rand32_get());
if (ret) {
_remove_ipv6_ping_handler();
} else {
printk("Sent a ping to %s\n", host);
}
return ret;
}
#else
#define _ping_ipv6(...) -EINVAL
#define _remove_ipv6_ping_handler()
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
static enum net_verdict _handle_ipv4_echo_reply(struct net_pkt *pkt);
static struct net_icmpv4_handler ping4_handler = {
.type = NET_ICMPV4_ECHO_REPLY,
.code = 0,
.handler = _handle_ipv4_echo_reply,
};
static inline void _remove_ipv4_ping_handler(void)
{
net_icmpv4_unregister_handler(&ping4_handler);
}
static enum net_verdict _handle_ipv4_echo_reply(struct net_pkt *pkt)
{
char addr[NET_IPV4_ADDR_LEN];
snprintk(addr, sizeof(addr), "%s",
net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->dst));
printk("Received echo reply from %s to %s\n",
net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->src), addr);
k_sem_give(&ping_timeout);
_remove_ipv4_ping_handler();
net_pkt_unref(pkt);
return NET_OK;
}
static int _ping_ipv4(char *host)
{
struct in_addr ipv4_target;
int ret;
if (net_addr_pton(AF_INET, host, &ipv4_target) < 0) {
return -EINVAL;
}
net_icmpv4_register_handler(&ping4_handler);
ret = net_icmpv4_send_echo_request(
net_if_ipv4_select_src_iface(&ipv4_target),
&ipv4_target,
sys_rand32_get(),
sys_rand32_get());
if (ret) {
_remove_ipv4_ping_handler();
} else {
printk("Sent a ping to %s\n", host);
}
return ret;
}
#else
#define _ping_ipv4(...) -EINVAL
#define _remove_ipv4_ping_handler()
#endif /* CONFIG_NET_IPV4 */
#endif /* CONFIG_NET_IPV6 || CONFIG_NET_IPV4 */
int net_shell_cmd_ping(int argc, char *argv[])
{
char *host;
int ret;
ARG_UNUSED(argc);
if (!strcmp(argv[0], "ping")) {
host = argv[1];
} else {
host = argv[2];
}
if (!host) {
printk("Target host missing\n");
return 0;
}
ret = _ping_ipv6(host);
if (!ret) {
goto wait_reply;
} else if (ret == -EIO) {
printk("Cannot send IPv6 ping\n");
return 0;
}
ret = _ping_ipv4(host);
if (ret) {
if (ret == -EIO) {
printk("Cannot send IPv4 ping\n");
} else if (ret == -EINVAL) {
printk("Invalid IP address\n");
}
return 0;
}
wait_reply:
ret = k_sem_take(&ping_timeout, K_SECONDS(2));
if (ret == -EAGAIN) {
printk("Ping timeout\n");
_remove_ipv6_ping_handler();
_remove_ipv4_ping_handler();
}
return 0;
}
int net_shell_cmd_route(int argc, char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_ROUTE)
net_if_foreach(iface_per_route_cb, NULL);
#else
printk("Network route support not compiled in.\n");
#endif
#if defined(CONFIG_NET_ROUTE_MCAST)
net_if_foreach(iface_per_mcast_route_cb, NULL);
#endif
return 0;
}
#if defined(CONFIG_NET_RPL)
static int power(int base, unsigned int exp)
{
int i, result = 1;
for (i = 0; i < exp; i++) {
result *= base;
}
return result;
}
static void rpl_parent(struct net_rpl_parent *parent, void *user_data)
{
int *count = user_data;
if (*count == 0) {
printk(" Parent Last TX Rank DTSN Flags DAG\t\t\t"
"Address\n");
}
(*count)++;
if (parent->dag) {
struct net_ipv6_nbr_data *data;
char addr[NET_IPV6_ADDR_LEN];
data = net_rpl_get_ipv6_nbr_data(parent);
if (data) {
snprintk(addr, sizeof(addr), "%s",
net_sprint_ipv6_addr(&data->addr));
} else {
snprintk(addr, sizeof(addr), "<unknown>");
}
printk("[%2d]%s %p %7d %5d %3d 0x%02x %s\t%s\n",
*count,
parent->dag->preferred_parent == parent ? "*" : " ",
parent, parent->last_tx_time, parent->rank,
parent->dtsn, parent->flags,
net_sprint_ipv6_addr(&parent->dag->dag_id),
addr);
}
}
#endif /* CONFIG_NET_RPL */
int net_shell_cmd_rpl(int argc, char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_RPL)
struct net_rpl_instance *instance;
enum net_rpl_mode mode;
int i, count;
mode = net_rpl_get_mode();
printk("RPL Configuration\n");
printk("=================\n");
printk("RPL mode : %s\n",
mode == NET_RPL_MODE_MESH ? "mesh" :
(mode == NET_RPL_MODE_FEATHER ? "feather" :
(mode == NET_RPL_MODE_LEAF ? "leaf" : "<unknown>")));
printk("Used objective function : %s\n",
IS_ENABLED(CONFIG_NET_RPL_MRHOF) ? "MRHOF" :
(IS_ENABLED(CONFIG_NET_RPL_OF0) ? "OF0" : "<unknown>"));
printk("Used routing metric : %s\n",
IS_ENABLED(CONFIG_NET_RPL_MC_NONE) ? "none" :
(IS_ENABLED(CONFIG_NET_RPL_MC_ETX) ? "estimated num of TX" :
(IS_ENABLED(CONFIG_NET_RPL_MC_ENERGY) ? "energy based" :
"<unknown>")));
printk("Mode of operation (MOP) : %s\n",
IS_ENABLED(CONFIG_NET_RPL_MOP2) ? "Storing, no mcast (MOP2)" :
(IS_ENABLED(CONFIG_NET_RPL_MOP3) ? "Storing (MOP3)" :
"<unknown>"));
printk("Send probes to nodes : %s\n",
IS_ENABLED(CONFIG_NET_RPL_PROBING) ? "enabled" : "disabled");
printk("Max instances : %d\n",
CONFIG_NET_RPL_MAX_INSTANCES);
printk("Max DAG / instance : %d\n",
CONFIG_NET_RPL_MAX_DAG_PER_INSTANCE);
printk("Min hop rank increment : %d\n",
CONFIG_NET_RPL_MIN_HOP_RANK_INC);
printk("Initial link metric : %d\n",
CONFIG_NET_RPL_INIT_LINK_METRIC);
printk("RPL preference value : %d\n",
CONFIG_NET_RPL_PREFERENCE);
printk("DAG grounded by default : %s\n",
IS_ENABLED(CONFIG_NET_RPL_GROUNDED) ? "yes" : "no");
printk("Default instance id : %d (0x%02x)\n",
CONFIG_NET_RPL_DEFAULT_INSTANCE,
CONFIG_NET_RPL_DEFAULT_INSTANCE);
printk("Insert Hop-by-hop option : %s\n",
IS_ENABLED(CONFIG_NET_RPL_INSERT_HBH_OPTION) ? "yes" : "no");
printk("Specify DAG when sending DAO : %s\n",
IS_ENABLED(CONFIG_NET_RPL_DAO_SPECIFY_DAG) ? "yes" : "no");
printk("DIO min interval : %d (%d ms)\n",
CONFIG_NET_RPL_DIO_INTERVAL_MIN,
power(2, CONFIG_NET_RPL_DIO_INTERVAL_MIN));
printk("DIO doublings interval : %d\n",
CONFIG_NET_RPL_DIO_INTERVAL_DOUBLINGS);
printk("DIO redundancy value : %d\n",
CONFIG_NET_RPL_DIO_REDUNDANCY);
printk("DAO sending timer value : %d sec\n",
CONFIG_NET_RPL_DAO_TIMER);
printk("DAO max retransmissions : %d\n",
CONFIG_NET_RPL_DAO_MAX_RETRANSMISSIONS);
printk("Node expecting DAO ack : %s\n",
IS_ENABLED(CONFIG_NET_RPL_DAO_ACK) ? "yes" : "no");
printk("Send DIS periodically : %s\n",
IS_ENABLED(CONFIG_NET_RPL_DIS_SEND) ? "yes" : "no");
#if defined(CONFIG_NET_RPL_DIS_SEND)
printk("DIS interval : %d sec\n",
CONFIG_NET_RPL_DIS_INTERVAL);
#endif
printk("Default route lifetime unit : %d sec\n",
CONFIG_NET_RPL_DEFAULT_LIFETIME_UNIT);
printk("Default route lifetime : %d\n",
CONFIG_NET_RPL_DEFAULT_LIFETIME);
#if defined(CONFIG_NET_RPL_MOP3)
printk("Multicast route lifetime : %d\n",
CONFIG_NET_RPL_MCAST_LIFETIME);
#endif
printk("\nRuntime status\n");
printk("==============\n");
instance = net_rpl_get_default_instance();
if (!instance) {
printk("No default RPL instance found.\n");
return 0;
}
printk("Default instance (id %d) : %p (%s)\n", instance->instance_id,
instance, instance->is_used ? "active" : "disabled");
if (instance->default_route) {
printk("Default route : %s\n",
net_sprint_ipv6_addr(
&instance->default_route->address.in6_addr));
}
#if defined(CONFIG_NET_STATISTICS_RPL)
printk("DIO statistics : intervals %d sent %d recv %d\n",
instance->dio_intervals, instance->dio_send_pkt,
instance->dio_recv_pkt);
#endif /* CONFIG_NET_STATISTICS_RPL */
printk("Instance DAGs :\n");
for (i = 0, count = 0; i < CONFIG_NET_RPL_MAX_DAG_PER_INSTANCE; i++) {
char prefix[NET_IPV6_ADDR_LEN];
if (!instance->dags[i].is_used) {
continue;
}
snprintk(prefix, sizeof(prefix), "%s",
net_sprint_ipv6_addr(
&instance->dags[i].prefix_info.prefix));
printk("[%2d]%s %s prefix %s/%d rank %d/%d ver %d flags %c%c "
"parent %p\n",
++count,
&instance->dags[i] == instance->current_dag ? "*" : " ",
net_sprint_ipv6_addr(&instance->dags[i].dag_id),
prefix, instance->dags[i].prefix_info.length,
instance->dags[i].rank, instance->dags[i].min_rank,
instance->dags[i].version,
instance->dags[i].is_grounded ? 'G' : 'g',
instance->dags[i].is_joined ? 'J' : 'j',
instance->dags[i].preferred_parent);
}
printk("\n");
count = 0;
i = net_rpl_foreach_parent(rpl_parent, &count);
if (i == 0) {
printk("No parents found.\n");
}
printk("\n");
#else
printk("RPL not enabled, set CONFIG_NET_RPL to enable it.\n");
#endif
return 0;
}
#if defined(CONFIG_INIT_STACKS)
extern K_THREAD_STACK_DEFINE(_main_stack, CONFIG_MAIN_STACK_SIZE);
extern K_THREAD_STACK_DEFINE(_interrupt_stack, CONFIG_ISR_STACK_SIZE);
extern K_THREAD_STACK_DEFINE(sys_work_q_stack,
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE);
#endif
int net_shell_cmd_stacks(int argc, char *argv[])
{
#if defined(CONFIG_INIT_STACKS)
unsigned int pcnt, unused;
#endif
struct net_stack_info *info;
ARG_UNUSED(argc);
ARG_UNUSED(argv);
for (info = __net_stack_start; info != __net_stack_end; info++) {
net_analyze_stack_get_values(K_THREAD_STACK_BUFFER(info->stack),
info->size, &pcnt, &unused);
#if defined(CONFIG_INIT_STACKS)
/* If the index is <0, then this stack is not part of stack
* array so do not print the index value in this case.
*/
if (info->idx >= 0) {
printk("%s-%d [%s-%d] stack size %zu/%zu bytes "
"unused %u usage %zu/%zu (%u %%)\n",
info->pretty_name, info->prio, info->name,
info->idx, info->orig_size,
info->size, unused,
info->size - unused, info->size, pcnt);
} else {
printk("%s [%s] stack size %zu/%zu bytes unused %u "
"usage %zu/%zu (%u %%)\n",
info->pretty_name, info->name, info->orig_size,
info->size, unused,
info->size - unused, info->size, pcnt);
}
#else
printk("%s [%s] stack size %zu usage not available\n",
info->pretty_name, info->name, info->orig_size);
#endif
}
#if defined(CONFIG_INIT_STACKS)
net_analyze_stack_get_values(K_THREAD_STACK_BUFFER(_main_stack),
K_THREAD_STACK_SIZEOF(_main_stack),
&pcnt, &unused);
printk("%s [%s] stack size %d/%d bytes unused %u usage"
" %d/%d (%u %%)\n",
"main", "_main_stack", CONFIG_MAIN_STACK_SIZE,
CONFIG_MAIN_STACK_SIZE, unused,
CONFIG_MAIN_STACK_SIZE - unused, CONFIG_MAIN_STACK_SIZE, pcnt);
net_analyze_stack_get_values(K_THREAD_STACK_BUFFER(_interrupt_stack),
K_THREAD_STACK_SIZEOF(_interrupt_stack),
&pcnt, &unused);
printk("%s [%s] stack size %d/%d bytes unused %u usage"
" %d/%d (%u %%)\n",
"ISR", "_interrupt_stack", CONFIG_ISR_STACK_SIZE,
CONFIG_ISR_STACK_SIZE, unused,
CONFIG_ISR_STACK_SIZE - unused, CONFIG_ISR_STACK_SIZE, pcnt);
net_analyze_stack_get_values(K_THREAD_STACK_BUFFER(sys_work_q_stack),
K_THREAD_STACK_SIZEOF(sys_work_q_stack),
&pcnt, &unused);
printk("%s [%s] stack size %d/%d bytes unused %u usage"
" %d/%d (%u %%)\n",
"WORKQ", "system workqueue",
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE,
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE, unused,
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE - unused,
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE, pcnt);
#else
printk("Enable CONFIG_INIT_STACKS to see usage information.\n");
#endif
return 0;
}
#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
static void net_shell_print_statistics_all(void)
{
net_if_foreach(net_shell_print_statistics, NULL);
}
#endif
int net_shell_cmd_stats(int argc, char *argv[])
{
#if defined(CONFIG_NET_STATISTICS)
int arg = 0;
if (strcmp(argv[arg], "stats") == 0) {
arg++;
}
if (!argv[arg]) {
/* Print global network statistics */
net_shell_print_statistics(NULL, NULL);
return 0;
}
#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
if (strcmp(argv[arg], "all") == 0) {
/* Print information about all network interfaces */
net_shell_print_statistics_all();
} else {
struct net_if *iface;
char *endptr;
int idx;
idx = strtol(argv[arg], &endptr, 10);
if (*endptr != '\0') {
printk("Invalid index %s\n", argv[arg]);
return 0;
}
iface = net_if_get_by_index(idx);
if (!iface) {
printk("No such interface in index %d\n", idx);
return 0;
}
net_shell_print_statistics(iface, NULL);
}
#else
printk("Per network interface statistics not collected.\n");
printk("Please enable CONFIG_NET_STATISTICS_PER_INTERFACE\n");
#endif /* CONFIG_NET_STATISTICS_PER_INTERFACE */
#else
ARG_UNUSED(argc);
ARG_UNUSED(argv);
printk("Network statistics not compiled in.\n");
#endif
return 0;
}
#if defined(CONFIG_NET_TCP)
static struct net_context *tcp_ctx;
#define TCP_CONNECT_TIMEOUT K_SECONDS(5) /* ms */
#define TCP_TIMEOUT K_SECONDS(2) /* ms */
static void tcp_connected(struct net_context *context,
int status,
void *user_data)
{
if (status < 0) {
printk("TCP connection failed (%d)\n", status);
net_context_put(context);
tcp_ctx = NULL;
} else {
printk("TCP connected\n");
}
}
#if defined(CONFIG_NET_IPV6)
static void get_my_ipv6_addr(struct net_if *iface,
struct sockaddr *myaddr)
{
const struct in6_addr *my6addr;
my6addr = net_if_ipv6_select_src_addr(iface,
&net_sin6(myaddr)->sin6_addr);
memcpy(&net_sin6(myaddr)->sin6_addr, my6addr, sizeof(struct in6_addr));
net_sin6(myaddr)->sin6_port = 0; /* let the IP stack to select */
}
#endif
#if defined(CONFIG_NET_IPV4)
static void get_my_ipv4_addr(struct net_if *iface,
struct sockaddr *myaddr)
{
/* Just take the first IPv4 address of an interface. */
memcpy(&net_sin(myaddr)->sin_addr,
&iface->config.ip.ipv4->unicast[0].address.in_addr,
sizeof(struct in_addr));
net_sin(myaddr)->sin_port = 0; /* let the IP stack to select */
}
#endif
static void print_connect_info(int family,
struct sockaddr *myaddr,
struct sockaddr *addr)
{
switch (family) {
case AF_INET:
#if defined(CONFIG_NET_IPV4)
printk("Connecting from %s:%u ",
net_sprint_ipv4_addr(&net_sin(myaddr)->sin_addr),
ntohs(net_sin(myaddr)->sin_port));
printk("to %s:%u\n",
net_sprint_ipv4_addr(&net_sin(addr)->sin_addr),
ntohs(net_sin(addr)->sin_port));
#else
printk("IPv4 not supported\n");
#endif
break;
case AF_INET6:
#if defined(CONFIG_NET_IPV6)
printk("Connecting from [%s]:%u ",
net_sprint_ipv6_addr(&net_sin6(myaddr)->sin6_addr),
ntohs(net_sin6(myaddr)->sin6_port));
printk("to [%s]:%u\n",
net_sprint_ipv6_addr(&net_sin6(addr)->sin6_addr),
ntohs(net_sin6(addr)->sin6_port));
#else
printk("IPv6 not supported\n");
#endif
break;
default:
printk("Unknown protocol family (%d)\n", family);
break;
}
}
static int tcp_connect(char *host, u16_t port, struct net_context **ctx)
{
struct sockaddr addr;
struct sockaddr myaddr;
struct net_nbr *nbr;
struct net_if *iface = net_if_get_default();
int addrlen;
int family;
int ret;
#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
ret = net_addr_pton(AF_INET6, host, &net_sin6(&addr)->sin6_addr);
if (ret < 0) {
printk("Invalid IPv6 address\n");
return 0;
}
net_sin6(&addr)->sin6_port = htons(port);
addrlen = sizeof(struct sockaddr_in6);
nbr = net_ipv6_nbr_lookup(NULL, &net_sin6(&addr)->sin6_addr);
if (nbr) {
iface = nbr->iface;
}
get_my_ipv6_addr(iface, &myaddr);
family = addr.sa_family = myaddr.sa_family = AF_INET6;
#endif
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
ARG_UNUSED(nbr);
ret = net_addr_pton(AF_INET, host, &net_sin(&addr)->sin_addr);
if (ret < 0) {
printk("Invalid IPv4 address\n");
return 0;
}
get_my_ipv4_addr(iface, &myaddr);
net_sin(&addr)->sin_port = htons(port);
addrlen = sizeof(struct sockaddr_in);
family = addr.sa_family = myaddr.sa_family = AF_INET;
#endif
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
ret = net_addr_pton(AF_INET6, host, &net_sin6(&addr)->sin6_addr);
if (ret < 0) {
ret = net_addr_pton(AF_INET, host, &net_sin(&addr)->sin_addr);
if (ret < 0) {
printk("Invalid IP address\n");
return 0;
}
net_sin(&addr)->sin_port = htons(port);
addrlen = sizeof(struct sockaddr_in);
get_my_ipv4_addr(iface, &myaddr);
family = addr.sa_family = myaddr.sa_family = AF_INET;
} else {
net_sin6(&addr)->sin6_port = htons(port);
addrlen = sizeof(struct sockaddr_in6);
nbr = net_ipv6_nbr_lookup(NULL, &net_sin6(&addr)->sin6_addr);
if (nbr) {
iface = nbr->iface;
}
get_my_ipv6_addr(iface, &myaddr);
family = addr.sa_family = myaddr.sa_family = AF_INET6;
}
#endif
print_connect_info(family, &myaddr, &addr);
ret = net_context_get(family, SOCK_STREAM, IPPROTO_TCP, ctx);
if (ret < 0) {
printk("Cannot get TCP context (%d)\n", ret);
return ret;
}
ret = net_context_bind(*ctx, &myaddr, addrlen);
if (ret < 0) {
printk("Cannot bind TCP (%d)\n", ret);
return ret;
}
return net_context_connect(*ctx, &addr, addrlen, tcp_connected,
K_NO_WAIT, NULL);
}
static void tcp_sent_cb(struct net_context *context,
int status,
void *token,
void *user_data)
{
printk("Message sent\n");
}
#endif
int net_shell_cmd_tcp(int argc, char *argv[])
{
#if defined(CONFIG_NET_TCP)
int arg = 1;
int ret;
if (argv[arg]) {
if (!strcmp(argv[arg], "connect")) {
/* tcp connect <ip> port */
char *endptr;
char *ip;
u16_t port;
if (tcp_ctx && net_context_is_used(tcp_ctx)) {
printk("Already connected\n");
return 0;
}
if (!argv[++arg]) {
printk("Peer IP address missing.\n");
return 0;
}
ip = argv[arg];
if (!argv[++arg]) {
printk("Peer port missing.\n");
return 0;
}
port = strtol(argv[arg], &endptr, 10);
if (*endptr != '\0') {
printk("Invalid port %s\n", argv[arg]);
return 0;
}
return tcp_connect(ip, port, &tcp_ctx);
}
if (!strcmp(argv[arg], "send")) {
/* tcp send <data> */
struct net_pkt *pkt;
if (!tcp_ctx || !net_context_is_used(tcp_ctx)) {
printk("Not connected\n");
return 0;
}
if (!argv[++arg]) {
printk("No data to send.\n");
return 0;
}
pkt = net_pkt_get_tx(tcp_ctx, TCP_TIMEOUT);
if (!pkt) {
printk("Out of pkts, msg cannot be sent.\n");
return 0;
}
ret = net_pkt_append_all(pkt, strlen(argv[arg]),
(u8_t *)argv[arg],
TCP_TIMEOUT);
if (!ret) {
printk("Cannot build msg (out of pkts)\n");
net_pkt_unref(pkt);
return 0;
}
ret = net_context_send(pkt, tcp_sent_cb, TCP_TIMEOUT,
NULL, NULL);
if (ret < 0) {
printk("Cannot send msg (%d)\n", ret);
net_pkt_unref(pkt);
return 0;
}
return 0;
}
if (!strcmp(argv[arg], "close")) {
/* tcp close */
if (!tcp_ctx || !net_context_is_used(tcp_ctx)) {
printk("Not connected\n");
return 0;
}
ret = net_context_put(tcp_ctx);
if (ret < 0) {
printk("Cannot close the connection (%d)\n",
ret);
return 0;
}
printk("Connection closed.\n");
tcp_ctx = NULL;
return 0;
}
printk("Unknown command '%s'\n", argv[arg]);
goto usage;
} else {
printk("Invalid command.\n");
usage:
printk("Usage:\n");
printk("\ttcp connect <ipaddr> port\n");
printk("\ttcp send <data>\n");
printk("\ttcp close\n");
}
#else
printk("TCP not enabled.\n");
#endif /* CONFIG_NET_TCP */
return 0;
}
#if defined(CONFIG_NET_VLAN)
static void iface_vlan_del_cb(struct net_if *iface, void *user_data)
{
u16_t vlan_tag = POINTER_TO_UINT(user_data);
int ret;
ret = net_eth_vlan_disable(iface, vlan_tag);
if (ret < 0) {
if (ret != -ESRCH) {
printk("Cannot delete VLAN tag %d from interface %p\n",
vlan_tag, iface);
}
return;
}
printk("VLAN tag %d removed from interface %p\n",
vlan_tag, iface);
}
static void iface_vlan_cb(struct net_if *iface, void *user_data)
{
struct ethernet_context *ctx = net_if_l2_data(iface);
int *count = user_data;
int i;
if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
return;
}
if (*count == 0) {
printk(" Interface Type Tag\n");
}
if (!ctx->vlan_enabled) {
printk("VLAN tag(s) not set\n");
return;
}
for (i = 0; i < NET_VLAN_MAX_COUNT; i++) {
if (!ctx->vlan[i].iface || ctx->vlan[i].iface != iface) {
continue;
}
if (ctx->vlan[i].tag == NET_VLAN_TAG_UNSPEC) {
continue;
}
printk("[%d] %p %s %d\n", net_if_get_by_iface(iface), iface,
iface2str(iface, NULL), ctx->vlan[i].tag);
break;
}
(*count)++;
}
#endif /* CONFIG_NET_VLAN */
int net_shell_cmd_vlan(int argc, char *argv[])
{
#if defined(CONFIG_NET_VLAN)
int arg = 1;
int ret;
u16_t tag;
if (!argv[arg]) {
int count = 0;
net_if_foreach(iface_vlan_cb, &count);
return 0;
}
if (!strcmp(argv[arg], "add")) {
/* vlan add <tag> <interface index> */
struct net_if *iface;
char *endptr;
u32_t iface_idx;
if (!argv[++arg]) {
printk("VLAN tag missing.\n");
return 0;
}
tag = strtol(argv[arg], &endptr, 10);
if (*endptr != '\0') {
printk("Invalid tag %s\n", argv[arg]);
return 0;
}
if (!argv[++arg]) {
printk("Network interface index missing.\n");
return 0;
}
iface_idx = strtol(argv[arg], &endptr, 10);
if (*endptr != '\0') {
printk("Invalid index %s\n", argv[arg]);
return 0;
}
iface = net_if_get_by_index(iface_idx);
if (!iface) {
printk("Network interface index %d is invalid.\n",
iface_idx);
return 0;
}
if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
printk("Network interface %p is not ethernet "
"interface\n", iface);
return 0;
}
ret = net_eth_vlan_enable(iface, tag);
if (ret < 0) {
if (ret == -ENOENT) {
printk("No IP address configured.\n");
}
printk("Cannot set VLAN tag (%d)\n", ret);
return 0;
}
printk("VLAN tag %d set to interface %p\n", tag, iface);
return 0;
}
if (!strcmp(argv[arg], "del")) {
/* vlan del <tag> */
char *endptr;
if (!argv[++arg]) {
printk("VLAN tag missing.\n");
return 0;
}
tag = strtol(argv[arg], &endptr, 10);
if (*endptr != '\0') {
printk("Invalid tag %s\n", argv[arg]);
return 0;
}
net_if_foreach(iface_vlan_del_cb,
UINT_TO_POINTER((u32_t)tag));
return 0;
}
printk("Unknown command '%s'\n", argv[arg]);
printk("Usage:\n");
printk("\tvlan add <tag> <interface index>\n");
printk("\tvlan del <tag>\n");
#else
printk("Set CONFIG_NET_VLAN to enable virtual LAN support.\n");
#endif /* CONFIG_NET_VLAN */
return 0;
}
static struct shell_cmd net_commands[] = {
/* Keep the commands in alphabetical order */
{ "allocs", net_shell_cmd_allocs,
"\n\tPrint network memory allocations" },
{ "app", net_shell_cmd_app,
"\n\tPrint network application API usage information" },
{ "arp", net_shell_cmd_arp,
"\n\tPrint information about IPv4 ARP cache\n"
"arp flush\n\tRemove all entries from ARP cache" },
{ "conn", net_shell_cmd_conn,
"\n\tPrint information about network connections" },
{ "dns", net_shell_cmd_dns, "\n\tShow how DNS is configured\n"
"dns cancel\n\tCancel all pending requests\n"
"dns <hostname> [A or AAAA]\n\tQuery IPv4 address (default) or "
"IPv6 address for a host name" },
{ "gptp", net_shell_cmd_gptp,
"\n\tPrint information about gPTP support\n"
"gptp <port>\n\tPrint detailed information about gPTP port" },
{ "http", net_shell_cmd_http,
"\n\tPrint information about active HTTP connections\n"
"http monitor\n\tStart monitoring HTTP connections\n"
"http\n\tTurn off HTTP connection monitoring" },
{ "iface", net_shell_cmd_iface,
"\n\tPrint information about network interfaces\n"
"iface up [idx]\n\tTake network interface up\n"
"iface down [idx]\n\tTake network interface down" },
{ "mem", net_shell_cmd_mem,
"\n\tPrint information about network memory usage" },
{ "nbr", net_shell_cmd_nbr, "\n\tPrint neighbor information\n"
"nbr rm <IPv6 address>\n\tRemove neighbor from cache" },
{ "ping", net_shell_cmd_ping, "<host>\n\tPing a network host" },
{ "route", net_shell_cmd_route, "\n\tShow network route" },
{ "rpl", net_shell_cmd_rpl, "\n\tShow RPL mesh routing status" },
{ "stacks", net_shell_cmd_stacks,
"\n\tShow network stacks information" },
{ "stats", net_shell_cmd_stats,
"\n\tShow network statistics\n"
"stats all\n\tShow network statistics for all network "
"interfaces\n"
"stats <idx>\n\tShow network statistics for one specific "
"network interfaces\n" },
{ "tcp", net_shell_cmd_tcp, "connect <ip> port\n\tConnect to TCP peer\n"
"tcp send <data>\n\tSend data to peer using TCP\n"
"tcp close\n\tClose TCP connection" },
{ "vlan", net_shell_cmd_vlan, "\n\tShow VLAN information\n"
"vlan add <vlan tag> <interface index>\n"
"\tAdd VLAN tag to the network interface\n"
"vlan del <vlan tag>\n"
"\tDelete VLAN tag from the network interface\n" },
{ NULL, NULL, NULL }
};
SHELL_REGISTER(NET_SHELL_MODULE, net_commands);