4545static PagerFlags arg_pager_flags = 0 ;
4646static bool arg_legend = true;
4747static bool arg_all = false;
48+ static bool arg_stats = false;
4849
4950static char * link_get_type_string (unsigned short iftype , sd_device * d ) {
5051 const char * t , * devtype ;
@@ -109,9 +110,16 @@ typedef struct LinkInfo {
109110 uint32_t tx_queues ;
110111 uint32_t rx_queues ;
111112
113+ union {
114+ struct rtnl_link_stats64 stats64 ;
115+ struct rtnl_link_stats stats ;
116+ };
117+
112118 bool has_mac_address :1 ;
113119 bool has_tx_queues :1 ;
114120 bool has_rx_queues :1 ;
121+ bool has_stats64 :1 ;
122+ bool has_stats :1 ;
115123} LinkInfo ;
116124
117125static int link_info_compare (const LinkInfo * a , const LinkInfo * b ) {
@@ -173,6 +181,11 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns) {
173181 sd_netlink_message_read_u32 (m , IFLA_NUM_TX_QUEUES , & info -> tx_queues ) >= 0 &&
174182 info -> tx_queues > 0 ;
175183
184+ if (sd_netlink_message_read (m , IFLA_STATS64 , sizeof info -> stats64 , & info -> stats64 ) >= 0 )
185+ info -> has_stats64 = true;
186+ else if (sd_netlink_message_read (m , IFLA_STATS , sizeof info -> stats , & info -> stats ) >= 0 )
187+ info -> has_stats = true;
188+
176189 return 1 ;
177190}
178191
@@ -799,6 +812,42 @@ static int dump_list(Table *table, const char *prefix, char **l) {
799812 return 0 ;
800813}
801814
815+ #define DUMP_STATS_ONE (name , val_name ) \
816+ r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); \
817+ if (r < 0) \
818+ return r; \
819+ r = table_add_cell_full(table, NULL, TABLE_STRING, name ":", \
820+ SIZE_MAX, SIZE_MAX, 0, 100, 0); \
821+ if (r < 0) \
822+ return r; \
823+ r = table_add_cell(table, NULL, info->has_stats64 ? TABLE_UINT64 : TABLE_UINT32, \
824+ info->has_stats64 ? (void*) &info->stats64.val_name : (void*) &info->stats.val_name); \
825+ if (r < 0) \
826+ return r;
827+
828+ static int dump_statistics (Table * table , const LinkInfo * info ) {
829+ int r ;
830+
831+ if (!arg_stats )
832+ return 0 ;
833+
834+ if (!info -> has_stats64 && !info -> has_stats )
835+ return 0 ;
836+
837+ DUMP_STATS_ONE ("Rx Packets" , rx_packets );
838+ DUMP_STATS_ONE ("Tx Packets" , tx_packets );
839+ DUMP_STATS_ONE ("Rx Bytes" , rx_bytes );
840+ DUMP_STATS_ONE ("Tx Bytes" , tx_bytes );
841+ DUMP_STATS_ONE ("Rx Errors" , rx_errors );
842+ DUMP_STATS_ONE ("Tx Errors" , tx_errors );
843+ DUMP_STATS_ONE ("Rx Dropped" , rx_dropped );
844+ DUMP_STATS_ONE ("Tx Dropped" , tx_dropped );
845+ DUMP_STATS_ONE ("Multicast Packets" , multicast );
846+ DUMP_STATS_ONE ("Collisions" , collisions );
847+
848+ return 0 ;
849+ }
850+
802851static int link_status_one (
803852 sd_netlink * rtnl ,
804853 sd_hwdb * hwdb ,
@@ -1061,6 +1110,10 @@ static int link_status_one(
10611110 if (r < 0 )
10621111 return r ;
10631112
1113+ r = dump_statistics (table , info );
1114+ if (r < 0 )
1115+ return r ;
1116+
10641117 return table_print (table , NULL );
10651118}
10661119
@@ -1415,8 +1468,9 @@ static int help(void) {
14151468 " --version Show package version\n"
14161469 " --no-pager Do not pipe output into a pager\n"
14171470 " --no-legend Do not show the headers and footers\n"
1418- " -a --all Show status for all links\n\n"
1419- "Commands:\n"
1471+ " -a --all Show status for all links\n"
1472+ " -s --stats Show detailed link statics\n"
1473+ "\nCommands:\n"
14201474 " list [PATTERN...] List links\n"
14211475 " status [PATTERN...] Show link status\n"
14221476 " lldp [PATTERN...] Show LLDP neighbors\n"
@@ -1444,6 +1498,7 @@ static int parse_argv(int argc, char *argv[]) {
14441498 { "no-pager" , no_argument , NULL , ARG_NO_PAGER },
14451499 { "no-legend" , no_argument , NULL , ARG_NO_LEGEND },
14461500 { "all" , no_argument , NULL , 'a' },
1501+ { "stats" , no_argument , NULL , 's' },
14471502 {}
14481503 };
14491504
@@ -1452,7 +1507,7 @@ static int parse_argv(int argc, char *argv[]) {
14521507 assert (argc >= 0 );
14531508 assert (argv );
14541509
1455- while ((c = getopt_long (argc , argv , "ha " , options , NULL )) >= 0 ) {
1510+ while ((c = getopt_long (argc , argv , "has " , options , NULL )) >= 0 ) {
14561511
14571512 switch (c ) {
14581513
@@ -1474,6 +1529,10 @@ static int parse_argv(int argc, char *argv[]) {
14741529 arg_all = true;
14751530 break ;
14761531
1532+ case 's' :
1533+ arg_stats = true;
1534+ break ;
1535+
14771536 case '?' :
14781537 return - EINVAL ;
14791538
0 commit comments