Skip to content

Commit a459b24

Browse files
committed
networkctl: optionally show link statistics
1 parent c095e5b commit a459b24

File tree

2 files changed

+73
-3
lines changed

2 files changed

+73
-3
lines changed

man/networkctl.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,17 @@
5858
</listitem>
5959
</varlistentry>
6060

61+
<varlistentry>
62+
<term>
63+
<option>-s</option>
64+
<option>--stats</option>
65+
</term>
66+
67+
<listitem>
68+
<para>Show link statistics with <command>status</command>.</para>
69+
</listitem>
70+
</varlistentry>
71+
6172
<xi:include href="standard-options.xml" xpointer="help" />
6273
<xi:include href="standard-options.xml" xpointer="version" />
6374
<xi:include href="standard-options.xml" xpointer="no-legend" />

src/network/networkctl.c

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
static PagerFlags arg_pager_flags = 0;
4646
static bool arg_legend = true;
4747
static bool arg_all = false;
48+
static bool arg_stats = false;
4849

4950
static 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

117125
static 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+
802851
static 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

Comments
 (0)