1 /*
2 * Copyright (c) 2016 Intel Corporation
3 * Copyright (c) 2023 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_DECLARE(net_shell);
10
11 #include <zephyr/net/net_stats.h>
12
13 #include "net_shell_private.h"
14
15 #include "../ip/net_stats.h"
16
17 #if defined(CONFIG_NET_STATISTICS)
18
19 #if NET_TC_COUNT > 1
priority2str(enum net_priority priority)20 static const char *priority2str(enum net_priority priority)
21 {
22 switch (priority) {
23 case NET_PRIORITY_BK:
24 return "BK"; /* Background */
25 case NET_PRIORITY_BE:
26 return "BE"; /* Best effort */
27 case NET_PRIORITY_EE:
28 return "EE"; /* Excellent effort */
29 case NET_PRIORITY_CA:
30 return "CA"; /* Critical applications */
31 case NET_PRIORITY_VI:
32 return "VI"; /* Video, < 100 ms latency and jitter */
33 case NET_PRIORITY_VO:
34 return "VO"; /* Voice, < 10 ms latency and jitter */
35 case NET_PRIORITY_IC:
36 return "IC"; /* Internetwork control */
37 case NET_PRIORITY_NC:
38 return "NC"; /* Network control */
39 }
40
41 return "??";
42 }
43 #endif
44
45 #if defined(CONFIG_NET_STATISTICS_ETHERNET) && \
46 defined(CONFIG_NET_STATISTICS_USER_API)
print_eth_stats(struct net_if * iface,struct net_stats_eth * data,const struct shell * sh)47 static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data,
48 const struct shell *sh)
49 {
50 PR("Statistics for Ethernet interface %p [%d]\n", iface,
51 net_if_get_by_iface(iface));
52
53 PR("Bytes received : %u\n", data->bytes.received);
54 PR("Bytes sent : %u\n", data->bytes.sent);
55 PR("Packets received : %u\n", data->pkts.rx);
56 PR("Packets sent : %u\n", data->pkts.tx);
57 PR("Bcast received : %u\n", data->broadcast.rx);
58 PR("Bcast sent : %u\n", data->broadcast.tx);
59 PR("Mcast received : %u\n", data->multicast.rx);
60 PR("Mcast sent : %u\n", data->multicast.tx);
61
62 PR("Send errors : %u\n", data->errors.tx);
63 PR("Receive errors : %u\n", data->errors.rx);
64 PR("Collisions : %u\n", data->collisions);
65 PR("Send Drops : %u\n", data->tx_dropped);
66 PR("Send timeouts : %u\n", data->tx_timeout_count);
67 PR("Send restarts : %u\n", data->tx_restart_queue);
68 PR("Unknown protocol : %u\n", data->unknown_protocol);
69
70 PR("Checksum offload : RX good %u errors %u\n",
71 data->csum.rx_csum_offload_good,
72 data->csum.rx_csum_offload_errors);
73 PR("Flow control : RX xon %u xoff %u TX xon %u xoff %u\n",
74 data->flow_control.rx_flow_control_xon,
75 data->flow_control.rx_flow_control_xoff,
76 data->flow_control.tx_flow_control_xon,
77 data->flow_control.tx_flow_control_xoff);
78 PR("ECC errors : uncorrected %u corrected %u\n",
79 data->error_details.uncorr_ecc_errors,
80 data->error_details.corr_ecc_errors);
81 PR("HW timestamp : RX cleared %u TX timeout %u skipped %u\n",
82 data->hw_timestamp.rx_hwtstamp_cleared,
83 data->hw_timestamp.tx_hwtstamp_timeouts,
84 data->hw_timestamp.tx_hwtstamp_skipped);
85
86 PR("RX errors : %5s %5s %5s %5s %5s %5s %5s %5s %5s %5s %5s\n",
87 "Len", "Over", "CRC", "Frame", "NoBuf", "Miss", "Long", "Short",
88 "Align", "DMA", "Alloc");
89 PR(" %5u %5u %5u %5u %5u %5u %5u %5u %5u %5u %5u\n",
90 data->error_details.rx_length_errors,
91 data->error_details.rx_over_errors,
92 data->error_details.rx_crc_errors,
93 data->error_details.rx_frame_errors,
94 data->error_details.rx_no_buffer_count,
95 data->error_details.rx_missed_errors,
96 data->error_details.rx_long_length_errors,
97 data->error_details.rx_short_length_errors,
98 data->error_details.rx_align_errors,
99 data->error_details.rx_dma_failed,
100 data->error_details.rx_buf_alloc_failed);
101 PR("TX errors : %5s %8s %5s %10s %7s %5s\n",
102 "Abort", "Carrier", "Fifo", "Heartbeat", "Window", "DMA");
103 PR(" %5u %8u %5u %10u %7u %5u\n",
104 data->error_details.tx_aborted_errors,
105 data->error_details.tx_carrier_errors,
106 data->error_details.tx_fifo_errors,
107 data->error_details.tx_heartbeat_errors,
108 data->error_details.tx_window_errors,
109 data->error_details.tx_dma_failed);
110
111 #if defined(CONFIG_NET_STATISTICS_ETHERNET_VENDOR)
112 if (data->vendor) {
113 PR("Vendor specific statistics for Ethernet "
114 "interface %p [%d]:\n",
115 iface, net_if_get_by_iface(iface));
116 size_t i = 0;
117
118 do {
119 PR("%s : %u\n", data->vendor[i].key,
120 data->vendor[i].value);
121 i++;
122 } while (data->vendor[i].key);
123 }
124 #endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */
125 }
126 #endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */
127
128 #if defined(CONFIG_NET_STATISTICS_PPP) && \
129 defined(CONFIG_NET_STATISTICS_USER_API)
print_ppp_stats(struct net_if * iface,struct net_stats_ppp * data,const struct shell * sh)130 static void print_ppp_stats(struct net_if *iface, struct net_stats_ppp *data,
131 const struct shell *sh)
132 {
133 PR("Frames recv %u\n", data->pkts.rx);
134 PR("Frames sent %u\n", data->pkts.tx);
135 PR("Frames dropped %u\n", data->drop);
136 PR("Bad FCS %u\n", data->chkerr);
137 }
138 #endif /* CONFIG_NET_STATISTICS_PPP && CONFIG_NET_STATISTICS_USER_API */
139
140 #if !defined(CONFIG_NET_NATIVE)
141 #define GET_STAT(a, b) 0
142 #endif
143
144 #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) || \
145 defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
146 #if (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1)
get_net_pkt_tc_stats_detail(struct net_if * iface,int i,bool is_tx)147 static char *get_net_pkt_tc_stats_detail(struct net_if *iface, int i,
148 bool is_tx)
149 {
150 static char extra_stats[sizeof("\t[0=xxxx us]") +
151 sizeof("->xxxx") *
152 NET_PKT_DETAIL_STATS_COUNT];
153 int j, total = 0, pos = 0;
154
155 pos += snprintk(extra_stats, sizeof(extra_stats), "\t[0");
156
157 for (j = 0; j < NET_PKT_DETAIL_STATS_COUNT; j++) {
158 net_stats_t count = 0;
159 uint32_t avg;
160
161 if (is_tx) {
162 #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) && (NET_TC_TX_COUNT > 1)
163 count = GET_STAT(iface,
164 tc.sent[i].tx_time_detail[j].count);
165 #endif
166 } else {
167 #if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) && (NET_TC_RX_COUNT > 1)
168 count = GET_STAT(iface,
169 tc.recv[i].rx_time_detail[j].count);
170 #endif
171 }
172
173 if (count == 0) {
174 break;
175 }
176
177 if (is_tx) {
178 #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) && (NET_TC_TX_COUNT > 1)
179 avg = (uint32_t)(GET_STAT(iface,
180 tc.sent[i].tx_time_detail[j].sum) /
181 (uint64_t)count);
182 #endif
183 } else {
184 #if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) && (NET_TC_RX_COUNT > 1)
185 avg = (uint32_t)(GET_STAT(iface,
186 tc.recv[i].rx_time_detail[j].sum) /
187 (uint64_t)count);
188 #endif
189 }
190
191 if (avg == 0) {
192 continue;
193 }
194
195 total += avg;
196
197 pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos,
198 "->%u", avg);
199 }
200
201 if (total == 0U) {
202 return "\0";
203 }
204
205 pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos,
206 "=%u us]", total);
207
208 return extra_stats;
209 }
210 #endif /* (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1) */
211
212 #if (NET_TC_TX_COUNT <= 1) || (NET_TC_RX_COUNT <= 1)
get_net_pkt_stats_detail(struct net_if * iface,bool is_tx)213 static char *get_net_pkt_stats_detail(struct net_if *iface, bool is_tx)
214 {
215 static char extra_stats[sizeof("\t[0=xxxx us]") + sizeof("->xxxx") *
216 NET_PKT_DETAIL_STATS_COUNT];
217 int j, total = 0, pos = 0;
218
219 pos += snprintk(extra_stats, sizeof(extra_stats), "\t[0");
220
221 for (j = 0; j < NET_PKT_DETAIL_STATS_COUNT; j++) {
222 net_stats_t count;
223 uint32_t avg;
224
225 if (is_tx) {
226 #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
227 count = GET_STAT(iface, tx_time_detail[j].count);
228 #endif
229 } else {
230 #if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
231 count = GET_STAT(iface, rx_time_detail[j].count);
232 #endif
233 }
234
235 if (count == 0) {
236 break;
237 }
238
239 if (is_tx) {
240 #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
241 avg = (uint32_t)(GET_STAT(iface,
242 tx_time_detail[j].sum) /
243 (uint64_t)count);
244 #endif
245 } else {
246 #if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
247 avg = (uint32_t)(GET_STAT(iface,
248 rx_time_detail[j].sum) /
249 (uint64_t)count);
250 #endif
251 }
252
253 if (avg == 0) {
254 continue;
255 }
256
257 total += avg;
258
259 pos += snprintk(extra_stats + pos,
260 sizeof(extra_stats) - pos,
261 "->%u", avg);
262 }
263
264 if (total == 0U) {
265 return "\0";
266 }
267
268 pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos,
269 "=%u us]", total);
270
271 return extra_stats;
272 }
273 #endif /* (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1) */
274
275 #else /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL || CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
276
277 #if defined(CONFIG_NET_PKT_TXTIME_STATS) || \
278 defined(CONFIG_NET_PKT_RXTIME_STATS)
279
280 #if (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1)
get_net_pkt_tc_stats_detail(struct net_if * iface,int i,bool is_tx)281 static char *get_net_pkt_tc_stats_detail(struct net_if *iface, int i,
282 bool is_tx)
283 {
284 ARG_UNUSED(iface);
285 ARG_UNUSED(i);
286 ARG_UNUSED(is_tx);
287
288 return "\0";
289 }
290 #endif
291
292 #if (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1)
get_net_pkt_stats_detail(struct net_if * iface,bool is_tx)293 static char *get_net_pkt_stats_detail(struct net_if *iface, bool is_tx)
294 {
295 ARG_UNUSED(iface);
296 ARG_UNUSED(is_tx);
297
298 return "\0";
299 }
300 #endif
301 #endif /* CONFIG_NET_PKT_TXTIME_STATS) || CONFIG_NET_PKT_RXTIME_STATS */
302 #endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL || CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
303
print_tc_tx_stats(const struct shell * sh,struct net_if * iface)304 static void print_tc_tx_stats(const struct shell *sh, struct net_if *iface)
305 {
306 #if NET_TC_TX_COUNT > 1
307 int i;
308
309 PR("TX traffic class statistics:\n");
310
311 #if defined(CONFIG_NET_PKT_TXTIME_STATS)
312 PR("TC Priority\tSent pkts\tbytes\ttime\n");
313
314 for (i = 0; i < NET_TC_TX_COUNT; i++) {
315 net_stats_t count = GET_STAT(iface,
316 tc.sent[i].tx_time.count);
317 if (count == 0) {
318 PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i,
319 priority2str(GET_STAT(iface, tc.sent[i].priority)),
320 GET_STAT(iface, tc.sent[i].priority),
321 GET_STAT(iface, tc.sent[i].pkts),
322 GET_STAT(iface, tc.sent[i].bytes));
323 } else {
324 PR("[%d] %s (%d)\t%d\t\t%d\t%u us%s\n", i,
325 priority2str(GET_STAT(iface, tc.sent[i].priority)),
326 GET_STAT(iface, tc.sent[i].priority),
327 GET_STAT(iface, tc.sent[i].pkts),
328 GET_STAT(iface, tc.sent[i].bytes),
329 (uint32_t)(GET_STAT(iface,
330 tc.sent[i].tx_time.sum) /
331 (uint64_t)count),
332 get_net_pkt_tc_stats_detail(iface, i, true));
333 }
334 }
335 #else
336 PR("TC Priority\tSent pkts\tbytes\n");
337
338 for (i = 0; i < NET_TC_TX_COUNT; i++) {
339 PR("[%d] %s (%d)\t%d\t\t%d\n", i,
340 priority2str(GET_STAT(iface, tc.sent[i].priority)),
341 GET_STAT(iface, tc.sent[i].priority),
342 GET_STAT(iface, tc.sent[i].pkts),
343 GET_STAT(iface, tc.sent[i].bytes));
344 }
345 #endif /* CONFIG_NET_PKT_TXTIME_STATS */
346 #else
347 ARG_UNUSED(sh);
348
349 #if defined(CONFIG_NET_PKT_TXTIME_STATS)
350 net_stats_t count = GET_STAT(iface, tx_time.count);
351
352 if (count != 0) {
353 PR("Avg %s net_pkt (%u) time %" PRIu32 " us%s\n", "TX", count,
354 (uint32_t)(GET_STAT(iface, tx_time.sum) / (uint64_t)count),
355 get_net_pkt_stats_detail(iface, true));
356 }
357 #else
358 ARG_UNUSED(iface);
359 #endif /* CONFIG_NET_PKT_TXTIME_STATS */
360 #endif /* NET_TC_TX_COUNT > 1 */
361 }
362
print_tc_rx_stats(const struct shell * sh,struct net_if * iface)363 static void print_tc_rx_stats(const struct shell *sh, struct net_if *iface)
364 {
365 #if NET_TC_RX_COUNT > 1
366 int i;
367
368 PR("RX traffic class statistics:\n");
369
370 #if defined(CONFIG_NET_PKT_RXTIME_STATS)
371 PR("TC Priority\tRecv pkts\tbytes\ttime\n");
372
373 for (i = 0; i < NET_TC_RX_COUNT; i++) {
374 net_stats_t count = GET_STAT(iface,
375 tc.recv[i].rx_time.count);
376 if (count == 0) {
377 PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i,
378 priority2str(GET_STAT(iface, tc.recv[i].priority)),
379 GET_STAT(iface, tc.recv[i].priority),
380 GET_STAT(iface, tc.recv[i].pkts),
381 GET_STAT(iface, tc.recv[i].bytes));
382 } else {
383 PR("[%d] %s (%d)\t%d\t\t%d\t%u us%s\n", i,
384 priority2str(GET_STAT(iface, tc.recv[i].priority)),
385 GET_STAT(iface, tc.recv[i].priority),
386 GET_STAT(iface, tc.recv[i].pkts),
387 GET_STAT(iface, tc.recv[i].bytes),
388 (uint32_t)(GET_STAT(iface,
389 tc.recv[i].rx_time.sum) /
390 (uint64_t)count),
391 get_net_pkt_tc_stats_detail(iface, i, false));
392 }
393 }
394 #else
395 PR("TC Priority\tRecv pkts\tbytes\n");
396
397 for (i = 0; i < NET_TC_RX_COUNT; i++) {
398 PR("[%d] %s (%d)\t%d\t\t%d\n", i,
399 priority2str(GET_STAT(iface, tc.recv[i].priority)),
400 GET_STAT(iface, tc.recv[i].priority),
401 GET_STAT(iface, tc.recv[i].pkts),
402 GET_STAT(iface, tc.recv[i].bytes));
403 }
404 #endif /* CONFIG_NET_PKT_RXTIME_STATS */
405 #else
406 ARG_UNUSED(sh);
407
408 #if defined(CONFIG_NET_PKT_RXTIME_STATS)
409 net_stats_t count = GET_STAT(iface, rx_time.count);
410
411 if (count != 0) {
412 PR("Avg %s net_pkt (%u) time %" PRIu32 " us%s\n", "RX", count,
413 (uint32_t)(GET_STAT(iface, rx_time.sum) / (uint64_t)count),
414 get_net_pkt_stats_detail(iface, false));
415 }
416 #else
417 ARG_UNUSED(iface);
418 #endif /* CONFIG_NET_PKT_RXTIME_STATS */
419
420 #endif /* NET_TC_RX_COUNT > 1 */
421 }
422
print_net_pm_stats(const struct shell * sh,struct net_if * iface)423 static void print_net_pm_stats(const struct shell *sh, struct net_if *iface)
424 {
425 #if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT)
426 PR("PM suspend stats:\n");
427 PR("\tLast time : %u ms\n",
428 GET_STAT(iface, pm.last_suspend_time));
429 PR("\tAverage time : %u ms\n",
430 (uint32_t)(GET_STAT(iface, pm.overall_suspend_time) /
431 GET_STAT(iface, pm.suspend_count)));
432 PR("\tTotal time : %" PRIu64 " ms\n",
433 GET_STAT(iface, pm.overall_suspend_time));
434 PR("\tHow many times: %u\n",
435 GET_STAT(iface, pm.suspend_count));
436 #else
437 ARG_UNUSED(sh);
438 ARG_UNUSED(iface);
439 #endif
440 }
441
net_shell_print_statistics(struct net_if * iface,void * user_data)442 static void net_shell_print_statistics(struct net_if *iface, void *user_data)
443 {
444 struct net_shell_user_data *data = user_data;
445 const struct shell *sh = data->sh;
446
447 if (iface) {
448 const char *extra;
449
450 PR("\nInterface %p (%s) [%d]\n", iface,
451 iface2str(iface, &extra), net_if_get_by_iface(iface));
452 PR("===========================%s\n", extra);
453 } else {
454 PR("\nGlobal statistics\n");
455 PR("=================\n");
456 }
457
458 #if defined(CONFIG_NET_STATISTICS_IPV6) && defined(CONFIG_NET_NATIVE_IPV6)
459 PR("IPv6 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
460 GET_STAT(iface, ipv6.recv),
461 GET_STAT(iface, ipv6.sent),
462 GET_STAT(iface, ipv6.drop),
463 GET_STAT(iface, ipv6.forwarded));
464 #if defined(CONFIG_NET_STATISTICS_IPV6_ND)
465 PR("IPv6 ND recv %d\tsent\t%d\tdrop\t%d\n",
466 GET_STAT(iface, ipv6_nd.recv),
467 GET_STAT(iface, ipv6_nd.sent),
468 GET_STAT(iface, ipv6_nd.drop));
469 #endif /* CONFIG_NET_STATISTICS_IPV6_ND */
470 #if defined(CONFIG_NET_STATISTICS_IPV6_PMTU)
471 PR("IPv6 PMTU recv %d\tsent\t%d\tdrop\t%d\n",
472 GET_STAT(iface, ipv6_pmtu.recv),
473 GET_STAT(iface, ipv6_pmtu.sent),
474 GET_STAT(iface, ipv6_pmtu.drop));
475 #endif /* CONFIG_NET_STATISTICS_IPV6_PMTU */
476 #if defined(CONFIG_NET_STATISTICS_MLD)
477 PR("IPv6 MLD recv %d\tsent\t%d\tdrop\t%d\n",
478 GET_STAT(iface, ipv6_mld.recv),
479 GET_STAT(iface, ipv6_mld.sent),
480 GET_STAT(iface, ipv6_mld.drop));
481 #endif /* CONFIG_NET_STATISTICS_MLD */
482 #endif /* CONFIG_NET_STATISTICS_IPV6 */
483
484 #if defined(CONFIG_NET_STATISTICS_IPV4) && defined(CONFIG_NET_NATIVE_IPV4)
485 PR("IPv4 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
486 GET_STAT(iface, ipv4.recv),
487 GET_STAT(iface, ipv4.sent),
488 GET_STAT(iface, ipv4.drop),
489 GET_STAT(iface, ipv4.forwarded));
490 #endif /* CONFIG_NET_STATISTICS_IPV4 */
491
492 PR("IP vhlerr %d\thblener\t%d\tlblener\t%d\n",
493 GET_STAT(iface, ip_errors.vhlerr),
494 GET_STAT(iface, ip_errors.hblenerr),
495 GET_STAT(iface, ip_errors.lblenerr));
496 PR("IP fragerr %d\tchkerr\t%d\tprotoer\t%d\n",
497 GET_STAT(iface, ip_errors.fragerr),
498 GET_STAT(iface, ip_errors.chkerr),
499 GET_STAT(iface, ip_errors.protoerr));
500
501 #if defined(CONFIG_NET_STATISTICS_IPV4_PMTU)
502 PR("IPv4 PMTU recv %d\tsent\t%d\tdrop\t%d\n",
503 GET_STAT(iface, ipv4_pmtu.recv),
504 GET_STAT(iface, ipv4_pmtu.sent),
505 GET_STAT(iface, ipv4_pmtu.drop));
506 #endif /* CONFIG_NET_STATISTICS_IPV4_PMTU */
507
508 #if defined(CONFIG_NET_STATISTICS_ICMP) && defined(CONFIG_NET_NATIVE_IPV4)
509 PR("ICMP recv %d\tsent\t%d\tdrop\t%d\n",
510 GET_STAT(iface, icmp.recv),
511 GET_STAT(iface, icmp.sent),
512 GET_STAT(iface, icmp.drop));
513 PR("ICMP typeer %d\tchkerr\t%d\n",
514 GET_STAT(iface, icmp.typeerr),
515 GET_STAT(iface, icmp.chkerr));
516 #endif
517 #if defined(CONFIG_NET_STATISTICS_IGMP)
518 PR("IGMP recv %d\tsent\t%d\tdrop\t%d\n",
519 GET_STAT(iface, ipv4_igmp.recv),
520 GET_STAT(iface, ipv4_igmp.sent),
521 GET_STAT(iface, ipv4_igmp.drop));
522 #endif /* CONFIG_NET_STATISTICS_IGMP */
523 #if defined(CONFIG_NET_STATISTICS_UDP) && defined(CONFIG_NET_NATIVE_UDP)
524 PR("UDP recv %d\tsent\t%d\tdrop\t%d\n",
525 GET_STAT(iface, udp.recv),
526 GET_STAT(iface, udp.sent),
527 GET_STAT(iface, udp.drop));
528 PR("UDP chkerr %d\n",
529 GET_STAT(iface, udp.chkerr));
530 #endif
531
532 #if defined(CONFIG_NET_STATISTICS_TCP) && defined(CONFIG_NET_NATIVE_TCP)
533 PR("TCP bytes recv %u\tsent\t%d\tresent\t%d\n",
534 GET_STAT(iface, tcp.bytes.received),
535 GET_STAT(iface, tcp.bytes.sent),
536 GET_STAT(iface, tcp.resent));
537 PR("TCP seg recv %d\tsent\t%d\tdrop\t%d\n",
538 GET_STAT(iface, tcp.recv),
539 GET_STAT(iface, tcp.sent),
540 GET_STAT(iface, tcp.seg_drop));
541 PR("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n",
542 GET_STAT(iface, tcp.rexmit),
543 GET_STAT(iface, tcp.chkerr),
544 GET_STAT(iface, tcp.ackerr));
545 PR("TCP seg rsterr %d\trst\t%d\n",
546 GET_STAT(iface, tcp.rsterr),
547 GET_STAT(iface, tcp.rst));
548 PR("TCP conn drop %d\tconnrst\t%d\n",
549 GET_STAT(iface, tcp.conndrop),
550 GET_STAT(iface, tcp.connrst));
551 PR("TCP pkt drop %d\n", GET_STAT(iface, tcp.drop));
552 #endif
553 #if defined(CONFIG_NET_STATISTICS_DNS)
554 PR("DNS recv %d\tsent\t%d\tdrop\t%d\n",
555 GET_STAT(iface, dns.recv),
556 GET_STAT(iface, dns.sent),
557 GET_STAT(iface, dns.drop));
558 #endif /* CONFIG_NET_STATISTICS_DNS */
559
560 PR("Bytes received %u\n", GET_STAT(iface, bytes.received));
561 PR("Bytes sent %u\n", GET_STAT(iface, bytes.sent));
562 PR("Processing err %d\n", GET_STAT(iface, processing_error));
563
564 print_tc_tx_stats(sh, iface);
565 print_tc_rx_stats(sh, iface);
566
567 #if defined(CONFIG_NET_STATISTICS_ETHERNET) && \
568 defined(CONFIG_NET_STATISTICS_USER_API)
569 if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
570 struct net_stats_eth eth_data;
571 int ret;
572
573 ret = net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, iface,
574 ð_data, sizeof(eth_data));
575 if (!ret) {
576 print_eth_stats(iface, ð_data, sh);
577 }
578 }
579 #endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */
580
581 #if defined(CONFIG_NET_STATISTICS_PPP) && \
582 defined(CONFIG_NET_STATISTICS_USER_API)
583 if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) {
584 struct net_stats_ppp ppp_data;
585 int ret;
586
587 ret = net_mgmt(NET_REQUEST_STATS_GET_PPP, iface,
588 &ppp_data, sizeof(ppp_data));
589 if (!ret) {
590 print_ppp_stats(iface, &ppp_data, sh);
591 }
592 }
593 #endif /* CONFIG_NET_STATISTICS_PPP && CONFIG_NET_STATISTICS_USER_API */
594
595 print_net_pm_stats(sh, iface);
596 }
597 #endif /* CONFIG_NET_STATISTICS */
598
599 #if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
net_shell_print_statistics_all(struct net_shell_user_data * data)600 static void net_shell_print_statistics_all(struct net_shell_user_data *data)
601 {
602 net_if_foreach(net_shell_print_statistics, data);
603 }
604 #endif
605
cmd_net_stats_all(const struct shell * sh,size_t argc,char * argv[])606 int cmd_net_stats_all(const struct shell *sh, size_t argc, char *argv[])
607 {
608 #if defined(CONFIG_NET_STATISTICS)
609 struct net_shell_user_data user_data;
610 #endif
611
612 #if defined(CONFIG_NET_STATISTICS)
613 user_data.sh = sh;
614
615 /* Print global network statistics */
616 net_shell_print_statistics_all(&user_data);
617 #else
618 ARG_UNUSED(argc);
619 ARG_UNUSED(argv);
620
621 PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS",
622 "statistics");
623 #endif
624
625 return 0;
626 }
627
cmd_net_stats_iface(const struct shell * sh,size_t argc,char * argv[])628 int cmd_net_stats_iface(const struct shell *sh, size_t argc, char *argv[])
629 {
630 #if defined(CONFIG_NET_STATISTICS)
631 #if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
632 struct net_shell_user_data data;
633 struct net_if *iface;
634 char *endptr;
635 int idx;
636 #endif
637 #endif
638
639 #if defined(CONFIG_NET_STATISTICS)
640 #if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
641 if (argv[1] == NULL) {
642 PR_WARNING("Network interface index missing!\n");
643 return -ENOEXEC;
644 }
645
646 idx = strtol(argv[1], &endptr, 10);
647 if (*endptr != '\0') {
648 PR_WARNING("Invalid index %s\n", argv[1]);
649 return -ENOEXEC;
650 }
651
652 iface = net_if_get_by_index(idx);
653 if (!iface) {
654 PR_WARNING("No such interface in index %d\n", idx);
655 return -ENOEXEC;
656 }
657
658 data.sh = sh;
659
660 net_shell_print_statistics(iface, &data);
661 #else
662 PR_INFO("Per network interface statistics not collected.\n");
663 PR_INFO("Please enable CONFIG_NET_STATISTICS_PER_INTERFACE\n");
664 #endif /* CONFIG_NET_STATISTICS_PER_INTERFACE */
665 #else
666 ARG_UNUSED(argc);
667 ARG_UNUSED(argv);
668
669 PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS",
670 "statistics");
671 #endif
672
673 return 0;
674 }
675
cmd_net_stats(const struct shell * sh,size_t argc,char * argv[])676 static int cmd_net_stats(const struct shell *sh, size_t argc, char *argv[])
677 {
678 #if defined(CONFIG_NET_STATISTICS)
679 if (!argv[1]) {
680 cmd_net_stats_all(sh, argc, argv);
681 return 0;
682 }
683
684 if (strcmp(argv[1], "reset") == 0) {
685 net_stats_reset(NULL);
686 } else {
687 cmd_net_stats_iface(sh, argc, argv);
688 }
689 #else
690 ARG_UNUSED(argc);
691 ARG_UNUSED(argv);
692
693 PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS",
694 "statistics");
695 #endif
696
697 return 0;
698 }
699
700 #if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION)
701
702 #include "iface_dynamic.h"
703
704 #endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */
705
706 SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_stats,
707 SHELL_CMD(all, NULL,
708 "Show network statistics for all network interfaces.",
709 cmd_net_stats_all),
710 SHELL_CMD(iface, IFACE_DYN_CMD,
711 "'net stats <index>' shows network statistics for "
712 "one specific network interface.",
713 cmd_net_stats_iface),
714 SHELL_SUBCMD_SET_END
715 );
716
717 SHELL_SUBCMD_ADD((net), stats, &net_cmd_stats,
718 "Show network statistics.",
719 cmd_net_stats, 1, 1);
720