From c85e96d0d1e53196abc389f6b1bfabefb3336aea Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 23 May 2023 16:47:47 +0300 Subject: [PATCH] cmd: net: add a 'net stats' command to dump network statistics Add a new option to the 'net' command which can be used to dump network statistics. To do this, 3 new callbacks are added to the eth_ops structure: .get_sset_count(), .get_strings(), .get_stats(). These callbacks have the same functions as in Linux: to return the number of counters, the strings which describe those counters and the actual values. Signed-off-by: Ioana Ciornei Reviewed-by: Ramon Fried Signed-off-by: Peng Fan --- cmd/net.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++- include/net.h | 6 ++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/cmd/net.c b/cmd/net.c index 68d406291e..dfe811f41a 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -691,8 +692,58 @@ static int do_net_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const ar return CMD_RET_SUCCESS; } +static int do_net_stats(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + int nstats, err, i, off; + struct udevice *dev; + u64 *values; + u8 *strings; + + if (argc < 2) + return CMD_RET_USAGE; + + err = uclass_get_device_by_name(UCLASS_ETH, argv[1], &dev); + if (err) { + printf("Could not find device %s\n", argv[1]); + return CMD_RET_FAILURE; + } + + if (!eth_get_ops(dev)->get_sset_count || + !eth_get_ops(dev)->get_strings || + !eth_get_ops(dev)->get_stats) { + printf("Driver does not implement stats dump!\n"); + return CMD_RET_FAILURE; + } + + nstats = eth_get_ops(dev)->get_sset_count(dev); + strings = kcalloc(nstats, ETH_GSTRING_LEN, GFP_KERNEL); + if (!strings) + return CMD_RET_FAILURE; + + values = kcalloc(nstats, sizeof(u64), GFP_KERNEL); + if (!values) + goto err_free_strings; + + eth_get_ops(dev)->get_strings(dev, strings); + eth_get_ops(dev)->get_stats(dev, values); + + off = 0; + for (i = 0; i < nstats; i++) { + printf(" %s: %llu\n", &strings[off], values[i]); + off += ETH_GSTRING_LEN; + }; + + return CMD_RET_SUCCESS; + +err_free_strings: + kfree(strings); + + return CMD_RET_FAILURE; +} + static struct cmd_tbl cmd_net[] = { U_BOOT_CMD_MKENT(list, 1, 0, do_net_list, "", ""), + U_BOOT_CMD_MKENT(stats, 2, 0, do_net_stats, "", ""), }; static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) @@ -714,9 +765,10 @@ static int do_net(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) } U_BOOT_CMD( - net, 2, 1, do_net, + net, 3, 1, do_net, "NET sub-system", "list - list available devices\n" + "stats - dump statistics for specified device\n" ); #if defined(CONFIG_CMD_NCSI) diff --git a/include/net.h b/include/net.h index 785cb1059e..e254df7d7f 100644 --- a/include/net.h +++ b/include/net.h @@ -167,6 +167,9 @@ enum eth_recv_flags { * to the network stack. This function should fill in the * eth_pdata::enetaddr field - optional * set_promisc: Enable or Disable promiscuous mode + * get_sset_count: Number of statistics counters + * get_string: Names of the statistic counters + * get_stats: The values of the statistic counters */ struct eth_ops { int (*start)(struct udevice *dev); @@ -178,6 +181,9 @@ struct eth_ops { int (*write_hwaddr)(struct udevice *dev); int (*read_rom_hwaddr)(struct udevice *dev); int (*set_promisc)(struct udevice *dev, bool enable); + int (*get_sset_count)(struct udevice *dev); + void (*get_strings)(struct udevice *dev, u8 *data); + void (*get_stats)(struct udevice *dev, u64 *data); }; #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops) -- 2.39.5