@@ -45,7 +45,7 @@ static const char *priority2str(enum net_priority priority)
45
45
#if defined(CONFIG_NET_STATISTICS_ETHERNET ) && \
46
46
defined(CONFIG_NET_STATISTICS_USER_API )
47
47
static void print_eth_stats (struct net_if * iface , struct net_stats_eth * data ,
48
- const struct shell * sh )
48
+ const struct shell * sh , struct net_shell_user_data * user_data )
49
49
{
50
50
PR ("Statistics for Ethernet interface %p [%d]\n" , iface ,
51
51
net_if_get_by_iface (iface ));
@@ -110,16 +110,46 @@ static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data,
110
110
111
111
#if defined(CONFIG_NET_STATISTICS_ETHERNET_VENDOR )
112
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
113
size_t i = 0 ;
114
+ enum net_shell_stats_format format = NET_SHELL_STATS_FORMAT_DEFAULT ;
115
+
116
+ if (user_data ) {
117
+ format = user_data -> vendor_stats_format ;
118
+ }
119
+
120
+ PR ("Vendor specific statistics for Ethernet interface %p [%d]:\n" ,
121
+ iface , net_if_get_by_iface (iface ));
122
+
123
+ /* Print key-value pairs if requested */
124
+ if (format == NET_SHELL_STATS_FORMAT_DEFAULT ||
125
+ format == NET_SHELL_STATS_FORMAT_KEY_VALUE ||
126
+ format == NET_SHELL_STATS_FORMAT_BOTH ) {
127
+ do {
128
+ PR ("%s : %u\n" , data -> vendor [i ].key , data -> vendor [i ].value );
129
+ i ++ ;
130
+ } while (data -> vendor [i ].key );
131
+ }
117
132
118
- do {
119
- PR ("%s : %u\n" , data -> vendor [i ].key ,
120
- data -> vendor [i ].value );
121
- i ++ ;
122
- } while (data -> vendor [i ].key );
133
+ /* Print hex blob if requested */
134
+ if (format == NET_SHELL_STATS_FORMAT_HEX_BLOB ||
135
+ format == NET_SHELL_STATS_FORMAT_BOTH ) {
136
+ /*
137
+ * Print vendor stats as a contiguous hex blob, little-endian, no delimiters.
138
+ * This format is suitable for direct typecasting to a C struct for offline parsing.
139
+ * Each value is output as 4 bytes, least significant byte first.
140
+ */
141
+ PR ("Vendor stats hex blob: " );
142
+ for (i = 0 ; data -> vendor [i ].key ; i ++ ) {
143
+ uint32_t v = data -> vendor [i ].value ;
144
+
145
+ PR ("%02x%02x%02x%02x" ,
146
+ (uint8_t )(v & 0xFF ),
147
+ (uint8_t )((v >> 8 ) & 0xFF ),
148
+ (uint8_t )((v >> 16 ) & 0xFF ),
149
+ (uint8_t )((v >> 24 ) & 0xFF ));
150
+ }
151
+ PR ("\n" );
152
+ }
123
153
}
124
154
#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */
125
155
}
@@ -591,7 +621,7 @@ static void net_shell_print_statistics(struct net_if *iface, void *user_data)
591
621
ret = net_mgmt (NET_REQUEST_STATS_GET_ETHERNET , iface ,
592
622
& eth_data , sizeof (eth_data ));
593
623
if (!ret ) {
594
- print_eth_stats (iface , & eth_data , sh );
624
+ print_eth_stats (iface , & eth_data , sh , data );
595
625
}
596
626
}
597
627
#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */
@@ -629,6 +659,18 @@ int cmd_net_stats_all(const struct shell *sh, size_t argc, char *argv[])
629
659
630
660
#if defined(CONFIG_NET_STATISTICS )
631
661
user_data .sh = sh ;
662
+ user_data .vendor_stats_format = NET_SHELL_STATS_FORMAT_DEFAULT ;
663
+
664
+ /* Parse format argument if provided */
665
+ if (argc > 1 ) {
666
+ if (strcmp (argv [1 ], "key-value" ) == 0 ) {
667
+ user_data .vendor_stats_format = NET_SHELL_STATS_FORMAT_KEY_VALUE ;
668
+ } else if (strcmp (argv [1 ], "hex-blob" ) == 0 ) {
669
+ user_data .vendor_stats_format = NET_SHELL_STATS_FORMAT_HEX_BLOB ;
670
+ } else if (strcmp (argv [1 ], "both" ) == 0 ) {
671
+ user_data .vendor_stats_format = NET_SHELL_STATS_FORMAT_BOTH ;
672
+ }
673
+ }
632
674
633
675
/* Print global network statistics */
634
676
net_shell_print_statistics_all (& user_data );
@@ -674,6 +716,18 @@ int cmd_net_stats_iface(const struct shell *sh, size_t argc, char *argv[])
674
716
}
675
717
676
718
data .sh = sh ;
719
+ data .vendor_stats_format = NET_SHELL_STATS_FORMAT_DEFAULT ;
720
+
721
+ /* Parse format argument if provided */
722
+ if (argc > 2 ) {
723
+ if (strcmp (argv [2 ], "key-value" ) == 0 ) {
724
+ data .vendor_stats_format = NET_SHELL_STATS_FORMAT_KEY_VALUE ;
725
+ } else if (strcmp (argv [2 ], "hex-blob" ) == 0 ) {
726
+ data .vendor_stats_format = NET_SHELL_STATS_FORMAT_HEX_BLOB ;
727
+ } else if (strcmp (argv [2 ], "both" ) == 0 ) {
728
+ data .vendor_stats_format = NET_SHELL_STATS_FORMAT_BOTH ;
729
+ }
730
+ }
677
731
678
732
net_shell_print_statistics (iface , & data );
679
733
#else
@@ -702,7 +756,8 @@ static int cmd_net_stats(const struct shell *sh, size_t argc, char *argv[])
702
756
if (strcmp (argv [1 ], "reset" ) == 0 ) {
703
757
net_stats_reset (NULL );
704
758
} else {
705
- cmd_net_stats_iface (sh , argc , argv );
759
+ /* Shift arguments for iface command */
760
+ cmd_net_stats_iface (sh , argc - 1 , & argv [1 ]);
706
761
}
707
762
#else
708
763
ARG_UNUSED (argc );
@@ -723,15 +778,20 @@ static int cmd_net_stats(const struct shell *sh, size_t argc, char *argv[])
723
778
724
779
SHELL_STATIC_SUBCMD_SET_CREATE (net_cmd_stats ,
725
780
SHELL_CMD (all , NULL ,
726
- "Show network statistics for all network interfaces." ,
781
+ "Show network statistics for all network interfaces.\n"
782
+ "Usage: net stats all [key-value|hex-blob|both]" ,
727
783
cmd_net_stats_all ),
728
784
SHELL_CMD (iface , IFACE_DYN_CMD ,
729
- "'net stats <index>' shows network statistics for "
730
- "one specific network interface." ,
785
+ "'net stats <index> [key-value|hex-blob|both]' shows network statistics for "
786
+ "one specific network interface.\n"
787
+ "Format options:\n"
788
+ " key-value: Show vendor stats as key-value pairs (default)\n"
789
+ " hex-blob: Show vendor stats as hex blob for parsing\n"
790
+ " both: Show both key-value and hex blob formats" ,
731
791
cmd_net_stats_iface ),
732
792
SHELL_SUBCMD_SET_END
733
793
);
734
794
735
795
SHELL_SUBCMD_ADD ((net ), stats , & net_cmd_stats ,
736
796
"Show network statistics." ,
737
- cmd_net_stats , 1 , 1 );
797
+ cmd_net_stats , 1 , 3 );
0 commit comments