Skip to content

Commit f70b105

Browse files
committed
net: lib: shell: Rejig statistics
Use the newly added API to get specific type of stats (if supported) but also keep the backwards compatibility. Signed-off-by: Chaitanya Tata <[email protected]>
1 parent 135ced9 commit f70b105

File tree

1 file changed

+152
-107
lines changed

1 file changed

+152
-107
lines changed

subsys/net/lib/shell/stats.c

Lines changed: 152 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
LOG_MODULE_DECLARE(net_shell);
1010

1111
#include <zephyr/net/net_stats.h>
12+
#include <zephyr/net/ethernet.h>
1213

1314
#include "net_shell_private.h"
1415

@@ -21,6 +22,12 @@ enum net_shell_stats_format {
2122
NET_SHELL_STATS_FORMAT_BOTH
2223
};
2324

25+
/** Shell stats options passed via user_data */
26+
struct net_shell_stats_options {
27+
enum net_shell_stats_format format;
28+
uint32_t type; /* Bitmask of ethernet_stats_type */
29+
};
30+
2431
#if defined(CONFIG_NET_STATISTICS)
2532

2633

@@ -55,74 +62,86 @@ static const char *priority2str(enum net_priority priority)
5562
static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data,
5663
const struct shell *sh, struct net_shell_user_data *user_data)
5764
{
58-
PR("Statistics for Ethernet interface %p [%d]\n", iface,
59-
net_if_get_by_iface(iface));
60-
61-
PR("Bytes received : %llu\n", data->bytes.received);
62-
PR("Bytes sent : %llu\n", data->bytes.sent);
63-
PR("Packets received : %u\n", data->pkts.rx);
64-
PR("Packets sent : %u\n", data->pkts.tx);
65-
PR("Bcast received : %u\n", data->broadcast.rx);
66-
PR("Bcast sent : %u\n", data->broadcast.tx);
67-
PR("Mcast received : %u\n", data->multicast.rx);
68-
PR("Mcast sent : %u\n", data->multicast.tx);
69-
70-
PR("Send errors : %u\n", data->errors.tx);
71-
PR("Receive errors : %u\n", data->errors.rx);
72-
PR("Collisions : %u\n", data->collisions);
73-
PR("Send Drops : %u\n", data->tx_dropped);
74-
PR("Send timeouts : %u\n", data->tx_timeout_count);
75-
PR("Send restarts : %u\n", data->tx_restart_queue);
76-
PR("Unknown protocol : %u\n", data->unknown_protocol);
77-
78-
PR("Checksum offload : RX good %u errors %u\n",
79-
data->csum.rx_csum_offload_good,
80-
data->csum.rx_csum_offload_errors);
81-
PR("Flow control : RX xon %u xoff %u TX xon %u xoff %u\n",
82-
data->flow_control.rx_flow_control_xon,
83-
data->flow_control.rx_flow_control_xoff,
84-
data->flow_control.tx_flow_control_xon,
85-
data->flow_control.tx_flow_control_xoff);
86-
PR("ECC errors : uncorrected %u corrected %u\n",
87-
data->error_details.uncorr_ecc_errors,
88-
data->error_details.corr_ecc_errors);
89-
PR("HW timestamp : RX cleared %u TX timeout %u skipped %u\n",
90-
data->hw_timestamp.rx_hwtstamp_cleared,
91-
data->hw_timestamp.tx_hwtstamp_timeouts,
92-
data->hw_timestamp.tx_hwtstamp_skipped);
93-
94-
PR("RX errors : %5s %5s %5s %5s %5s %5s %5s %5s %5s %5s %5s\n",
95-
"Len", "Over", "CRC", "Frame", "NoBuf", "Miss", "Long", "Short",
96-
"Align", "DMA", "Alloc");
97-
PR(" %5u %5u %5u %5u %5u %5u %5u %5u %5u %5u %5u\n",
98-
data->error_details.rx_length_errors,
99-
data->error_details.rx_over_errors,
100-
data->error_details.rx_crc_errors,
101-
data->error_details.rx_frame_errors,
102-
data->error_details.rx_no_buffer_count,
103-
data->error_details.rx_missed_errors,
104-
data->error_details.rx_long_length_errors,
105-
data->error_details.rx_short_length_errors,
106-
data->error_details.rx_align_errors,
107-
data->error_details.rx_dma_failed,
108-
data->error_details.rx_buf_alloc_failed);
109-
PR("TX errors : %5s %8s %5s %10s %7s %5s\n",
110-
"Abort", "Carrier", "Fifo", "Heartbeat", "Window", "DMA");
111-
PR(" %5u %8u %5u %10u %7u %5u\n",
112-
data->error_details.tx_aborted_errors,
113-
data->error_details.tx_carrier_errors,
114-
data->error_details.tx_fifo_errors,
115-
data->error_details.tx_heartbeat_errors,
116-
data->error_details.tx_window_errors,
117-
data->error_details.tx_dma_failed);
65+
struct net_shell_stats_options *opts = NULL;
66+
uint32_t type = ETHERNET_STATS_TYPE_ALL;
67+
68+
if (user_data != NULL && user_data->user_data != NULL) {
69+
opts = (struct net_shell_stats_options *)user_data->user_data;
70+
type = opts->type;
71+
}
72+
73+
/* Print common stats if requested */
74+
if (type & ETHERNET_STATS_TYPE_COMMON) {
75+
PR("Statistics for Ethernet interface %p [%d]\n", iface,
76+
net_if_get_by_iface(iface));
77+
78+
PR("Bytes received : %llu\n", data->bytes.received);
79+
PR("Bytes sent : %llu\n", data->bytes.sent);
80+
PR("Packets received : %u\n", data->pkts.rx);
81+
PR("Packets sent : %u\n", data->pkts.tx);
82+
PR("Bcast received : %u\n", data->broadcast.rx);
83+
PR("Bcast sent : %u\n", data->broadcast.tx);
84+
PR("Mcast received : %u\n", data->multicast.rx);
85+
PR("Mcast sent : %u\n", data->multicast.tx);
86+
87+
PR("Send errors : %u\n", data->errors.tx);
88+
PR("Receive errors : %u\n", data->errors.rx);
89+
PR("Collisions : %u\n", data->collisions);
90+
PR("Send Drops : %u\n", data->tx_dropped);
91+
PR("Send timeouts : %u\n", data->tx_timeout_count);
92+
PR("Send restarts : %u\n", data->tx_restart_queue);
93+
PR("Unknown protocol : %u\n", data->unknown_protocol);
94+
95+
PR("Checksum offload : RX good %u errors %u\n",
96+
data->csum.rx_csum_offload_good,
97+
data->csum.rx_csum_offload_errors);
98+
PR("Flow control : RX xon %u xoff %u TX xon %u xoff %u\n",
99+
data->flow_control.rx_flow_control_xon,
100+
data->flow_control.rx_flow_control_xoff,
101+
data->flow_control.tx_flow_control_xon,
102+
data->flow_control.tx_flow_control_xoff);
103+
PR("ECC errors : uncorrected %u corrected %u\n",
104+
data->error_details.uncorr_ecc_errors,
105+
data->error_details.corr_ecc_errors);
106+
PR("HW timestamp : RX cleared %u TX timeout %u skipped %u\n",
107+
data->hw_timestamp.rx_hwtstamp_cleared,
108+
data->hw_timestamp.tx_hwtstamp_timeouts,
109+
data->hw_timestamp.tx_hwtstamp_skipped);
110+
111+
PR("RX errors : %5s %5s %5s %5s %5s %5s %5s %5s %5s %5s %5s\n",
112+
"Len", "Over", "CRC", "Frame", "NoBuf", "Miss", "Long", "Short",
113+
"Align", "DMA", "Alloc");
114+
PR(" %5u %5u %5u %5u %5u %5u %5u %5u %5u %5u %5u\n",
115+
data->error_details.rx_length_errors,
116+
data->error_details.rx_over_errors,
117+
data->error_details.rx_crc_errors,
118+
data->error_details.rx_frame_errors,
119+
data->error_details.rx_no_buffer_count,
120+
data->error_details.rx_missed_errors,
121+
data->error_details.rx_long_length_errors,
122+
data->error_details.rx_short_length_errors,
123+
data->error_details.rx_align_errors,
124+
data->error_details.rx_dma_failed,
125+
data->error_details.rx_buf_alloc_failed);
126+
PR("TX errors : %5s %8s %5s %10s %7s %5s\n",
127+
"Abort", "Carrier", "Fifo", "Heartbeat", "Window", "DMA");
128+
PR(" %5u %8u %5u %10u %7u %5u\n",
129+
data->error_details.tx_aborted_errors,
130+
data->error_details.tx_carrier_errors,
131+
data->error_details.tx_fifo_errors,
132+
data->error_details.tx_heartbeat_errors,
133+
data->error_details.tx_window_errors,
134+
data->error_details.tx_dma_failed);
135+
}
118136

119137
#if defined(CONFIG_NET_STATISTICS_ETHERNET_VENDOR)
120-
if (data->vendor) {
121-
size_t i = 0;
138+
/* Print vendor stats if requested - format options only apply here */
139+
if ((type & ETHERNET_STATS_TYPE_VENDOR) && data->vendor) {
122140
enum net_shell_stats_format format = NET_SHELL_STATS_FORMAT_DEFAULT;
141+
size_t i = 0;
123142

124-
if (user_data != NULL) {
125-
format = *(enum net_shell_stats_format *)user_data->user_data;
143+
if (opts != NULL) {
144+
format = opts->format;
126145
}
127146

128147
PR("Vendor specific statistics for Ethernet interface %p [%d]:\n",
@@ -619,13 +638,30 @@ static void net_shell_print_statistics(struct net_if *iface, void *user_data)
619638
#if defined(CONFIG_NET_STATISTICS_ETHERNET) && \
620639
defined(CONFIG_NET_STATISTICS_USER_API)
621640
if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
622-
struct net_stats_eth eth_data;
623-
int ret;
641+
const struct ethernet_api *eth_api;
642+
struct net_stats_eth *eth_data = NULL;
643+
uint32_t type = ETHERNET_STATS_TYPE_ALL;
624644

625-
ret = net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, iface,
626-
&eth_data, sizeof(eth_data));
627-
if (!ret) {
628-
print_eth_stats(iface, &eth_data, sh, data);
645+
if (data != NULL && data->user_data != NULL) {
646+
struct net_shell_stats_options *opts = data->user_data;
647+
648+
type = opts->type;
649+
}
650+
651+
eth_api = net_if_get_device(iface)->api;
652+
if (eth_api != NULL) {
653+
/* Use get_stats_type if available for type filtering */
654+
if (eth_api->get_stats_type != NULL) {
655+
eth_data = eth_api->get_stats_type(
656+
net_if_get_device(iface), type);
657+
} else if (eth_api->get_stats != NULL) {
658+
eth_data = eth_api->get_stats(
659+
net_if_get_device(iface));
660+
}
661+
}
662+
663+
if (eth_data != NULL) {
664+
print_eth_stats(iface, eth_data, sh, data);
629665
}
630666
}
631667
#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */
@@ -653,31 +689,45 @@ static void net_shell_print_statistics_all(struct net_shell_user_data *data)
653689
net_if_foreach(net_shell_print_statistics, data);
654690
}
655691
}
692+
693+
static void parse_stats_options(size_t argc, char *argv[], int start_idx,
694+
struct net_shell_stats_options *opts)
695+
{
696+
opts->format = NET_SHELL_STATS_FORMAT_DEFAULT;
697+
opts->type = ETHERNET_STATS_TYPE_ALL;
698+
699+
for (int i = start_idx; i < argc && argv[i] != NULL; i++) {
700+
/* Format options */
701+
if (strcmp(argv[i], "key-value") == 0) {
702+
opts->format = NET_SHELL_STATS_FORMAT_KEY_VALUE;
703+
} else if (strcmp(argv[i], "hex-blob") == 0) {
704+
opts->format = NET_SHELL_STATS_FORMAT_HEX_BLOB;
705+
} else if (strcmp(argv[i], "both") == 0) {
706+
opts->format = NET_SHELL_STATS_FORMAT_BOTH;
707+
/* Type filter options */
708+
} else if (strcmp(argv[i], "common") == 0) {
709+
opts->type = ETHERNET_STATS_TYPE_COMMON;
710+
} else if (strcmp(argv[i], "vendor") == 0) {
711+
opts->type = ETHERNET_STATS_TYPE_VENDOR;
712+
} else if (strcmp(argv[i], "all") == 0) {
713+
opts->type = ETHERNET_STATS_TYPE_ALL;
714+
}
715+
}
716+
}
656717
#endif /* CONFIG_NET_STATISTICS */
657718

658719
int cmd_net_stats_all(const struct shell *sh, size_t argc, char *argv[])
659720
{
660721
#if defined(CONFIG_NET_STATISTICS)
661722
struct net_shell_user_data user_data;
662-
#endif
663-
664-
#if defined(CONFIG_NET_STATISTICS)
665-
enum net_shell_stats_format format = NET_SHELL_STATS_FORMAT_DEFAULT;
723+
struct net_shell_stats_options opts;
666724

667725
user_data.sh = sh;
668726

669-
/* Parse format argument if provided */
670-
if (argc > 1) {
671-
if (strcmp(argv[1], "key-value") == 0) {
672-
format = NET_SHELL_STATS_FORMAT_KEY_VALUE;
673-
} else if (strcmp(argv[1], "hex-blob") == 0) {
674-
format = NET_SHELL_STATS_FORMAT_HEX_BLOB;
675-
} else if (strcmp(argv[1], "both") == 0) {
676-
format = NET_SHELL_STATS_FORMAT_BOTH;
677-
}
678-
}
727+
/* Parse options starting from argv[1] */
728+
parse_stats_options(argc, argv, 1, &opts);
679729

680-
user_data.user_data = &format;
730+
user_data.user_data = &opts;
681731

682732
/* Print global network statistics */
683733
net_shell_print_statistics_all(&user_data);
@@ -697,6 +747,7 @@ int cmd_net_stats_iface(const struct shell *sh, size_t argc, char *argv[])
697747
#if defined(CONFIG_NET_STATISTICS)
698748
#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
699749
struct net_shell_user_data data;
750+
struct net_shell_stats_options opts;
700751
struct net_if *iface;
701752
char *endptr;
702753
int idx;
@@ -722,22 +773,12 @@ int cmd_net_stats_iface(const struct shell *sh, size_t argc, char *argv[])
722773
return -ENOEXEC;
723774
}
724775

725-
enum net_shell_stats_format format = NET_SHELL_STATS_FORMAT_DEFAULT;
726-
727776
data.sh = sh;
728777

729-
/* Parse format argument if provided */
730-
if (argc > 2) {
731-
if (strcmp(argv[2], "key-value") == 0) {
732-
format = NET_SHELL_STATS_FORMAT_KEY_VALUE;
733-
} else if (strcmp(argv[2], "hex-blob") == 0) {
734-
format = NET_SHELL_STATS_FORMAT_HEX_BLOB;
735-
} else if (strcmp(argv[2], "both") == 0) {
736-
format = NET_SHELL_STATS_FORMAT_BOTH;
737-
}
738-
}
778+
/* Parse options starting from argv[2] */
779+
parse_stats_options(argc, argv, 2, &opts);
739780

740-
data.user_data = &format;
781+
data.user_data = &opts;
741782

742783
net_shell_print_statistics(iface, &data);
743784
#else
@@ -766,8 +807,8 @@ static int cmd_net_stats(const struct shell *sh, size_t argc, char *argv[])
766807
if (strcmp(argv[1], "reset") == 0) {
767808
net_stats_reset(NULL);
768809
} else {
769-
/* Shift arguments for iface command */
770-
cmd_net_stats_iface(sh, argc - 1, &argv[1]);
810+
/* Pass arguments directly - cmd_net_stats_iface expects index in argv[1] */
811+
cmd_net_stats_iface(sh, argc, argv);
771812
}
772813
#else
773814
ARG_UNUSED(argc);
@@ -789,19 +830,23 @@ static int cmd_net_stats(const struct shell *sh, size_t argc, char *argv[])
789830
SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_stats,
790831
SHELL_CMD(all, NULL,
791832
"Show network statistics for all network interfaces.\n"
792-
"Usage: net stats all [key-value|hex-blob|both]",
833+
"Usage: net stats all [common|vendor|all] [key-value|hex-blob|both]",
793834
cmd_net_stats_all),
794835
SHELL_CMD(iface, IFACE_DYN_CMD,
795-
"'net stats <index> [key-value|hex-blob|both]' shows network statistics for "
836+
"'net stats <index> [options]' shows network statistics for "
796837
"one specific network interface.\n"
797-
"Format options:\n"
798-
" key-value: Show vendor stats as key-value pairs (default)\n"
799-
" hex-blob: Show vendor stats as hex blob for parsing\n"
800-
" both: Show both key-value and hex blob formats",
838+
"Type filter:\n"
839+
" common: Only common stats (skips FW query)\n"
840+
" vendor: Only vendor-specific stats\n"
841+
" all: All stats (default)\n"
842+
"Vendor stats format (only applies when vendor stats shown):\n"
843+
" key-value: Key-value pairs (default)\n"
844+
" hex-blob: Hex blob for parsing\n"
845+
" both: Both formats",
801846
cmd_net_stats_iface),
802847
SHELL_SUBCMD_SET_END
803848
);
804849

805850
SHELL_SUBCMD_ADD((net), stats, &net_cmd_stats,
806851
"Show network statistics.",
807-
cmd_net_stats, 1, 3);
852+
cmd_net_stats, 1, 4);

0 commit comments

Comments
 (0)