|
|
268297 |
From dd5f8a5e8a13ce389269d6be24ba17a903dc6fd9 Mon Sep 17 00:00:00 2001
|
|
|
268297 |
From: Jakub Kicinski <kuba@kernel.org>
|
|
|
268297 |
Date: Sun, 18 Oct 2020 14:31:51 -0700
|
|
|
268297 |
Subject: [PATCH 33/37] pause: add support for dumping statistics
|
|
|
268297 |
|
|
|
268297 |
Add support for requesting pause frame stats from the kernel.
|
|
|
268297 |
|
|
|
268297 |
# ./ethtool -I -a eth0
|
|
|
268297 |
Pause parameters for eth0:
|
|
|
268297 |
Autonegotiate: on
|
|
|
268297 |
RX: on
|
|
|
268297 |
TX: on
|
|
|
268297 |
Statistics:
|
|
|
268297 |
tx_pause_frames: 1
|
|
|
268297 |
rx_pause_frames: 1
|
|
|
268297 |
|
|
|
268297 |
# ./ethtool -I --json -a eth0
|
|
|
268297 |
[ {
|
|
|
268297 |
"ifname": "eth0",
|
|
|
268297 |
"autonegotiate": true,
|
|
|
268297 |
"rx": true,
|
|
|
268297 |
"tx": true,
|
|
|
268297 |
"statistics": {
|
|
|
268297 |
"tx_pause_frames": 1,
|
|
|
268297 |
"rx_pause_frames": 1
|
|
|
268297 |
}
|
|
|
268297 |
} ]
|
|
|
268297 |
|
|
|
268297 |
v2: - correct print format for u64
|
|
|
268297 |
|
|
|
268297 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
268297 |
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
|
|
|
268297 |
(cherry picked from commit 1166ed2fbc603e739759961a77c7ecb5cf2d5443)
|
|
|
268297 |
---
|
|
|
268297 |
netlink/pause.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
|
268297 |
1 file changed, 66 insertions(+), 1 deletion(-)
|
|
|
268297 |
|
|
|
268297 |
diff --git a/netlink/pause.c b/netlink/pause.c
|
|
|
268297 |
index c54488d71fce..867d0da71f72 100644
|
|
|
268297 |
--- a/netlink/pause.c
|
|
|
268297 |
+++ b/netlink/pause.c
|
|
|
268297 |
@@ -5,6 +5,7 @@
|
|
|
268297 |
*/
|
|
|
268297 |
|
|
|
268297 |
#include <errno.h>
|
|
|
268297 |
+#include <inttypes.h>
|
|
|
268297 |
#include <string.h>
|
|
|
268297 |
#include <stdio.h>
|
|
|
268297 |
|
|
|
268297 |
@@ -105,6 +106,62 @@ out:
|
|
|
268297 |
return ret;
|
|
|
268297 |
}
|
|
|
268297 |
|
|
|
268297 |
+static int show_pause_stats(const struct nlattr *nest)
|
|
|
268297 |
+{
|
|
|
268297 |
+ const struct nlattr *tb[ETHTOOL_A_PAUSE_STAT_MAX + 1] = {};
|
|
|
268297 |
+ DECLARE_ATTR_TB_INFO(tb);
|
|
|
268297 |
+ static const struct {
|
|
|
268297 |
+ unsigned int attr;
|
|
|
268297 |
+ char *name;
|
|
|
268297 |
+ } stats[] = {
|
|
|
268297 |
+ { ETHTOOL_A_PAUSE_STAT_TX_FRAMES, "tx_pause_frames" },
|
|
|
268297 |
+ { ETHTOOL_A_PAUSE_STAT_RX_FRAMES, "rx_pause_frames" },
|
|
|
268297 |
+ };
|
|
|
268297 |
+ bool header = false;
|
|
|
268297 |
+ unsigned int i;
|
|
|
268297 |
+ size_t n;
|
|
|
268297 |
+ int ret;
|
|
|
268297 |
+
|
|
|
268297 |
+ ret = mnl_attr_parse_nested(nest, attr_cb, &tb_info);
|
|
|
268297 |
+ if (ret < 0)
|
|
|
268297 |
+ return ret;
|
|
|
268297 |
+
|
|
|
268297 |
+ open_json_object("statistics");
|
|
|
268297 |
+ for (i = 0; i < ARRAY_SIZE(stats); i++) {
|
|
|
268297 |
+ char fmt[32];
|
|
|
268297 |
+
|
|
|
268297 |
+ if (!tb[stats[i].attr])
|
|
|
268297 |
+ continue;
|
|
|
268297 |
+
|
|
|
268297 |
+ if (!header && !is_json_context()) {
|
|
|
268297 |
+ printf("Statistics:\n");
|
|
|
268297 |
+ header = true;
|
|
|
268297 |
+ }
|
|
|
268297 |
+
|
|
|
268297 |
+ if (mnl_attr_validate(tb[stats[i].attr], MNL_TYPE_U64)) {
|
|
|
268297 |
+ fprintf(stderr, "malformed netlink message (statistic)\n");
|
|
|
268297 |
+ goto err_close_stats;
|
|
|
268297 |
+ }
|
|
|
268297 |
+
|
|
|
268297 |
+ n = snprintf(fmt, sizeof(fmt), " %s: %%" PRIu64 "\n",
|
|
|
268297 |
+ stats[i].name);
|
|
|
268297 |
+ if (n >= sizeof(fmt)) {
|
|
|
268297 |
+ fprintf(stderr, "internal error - malformed label\n");
|
|
|
268297 |
+ goto err_close_stats;
|
|
|
268297 |
+ }
|
|
|
268297 |
+
|
|
|
268297 |
+ print_u64(PRINT_ANY, stats[i].name, fmt,
|
|
|
268297 |
+ mnl_attr_get_u64(tb[stats[i].attr]));
|
|
|
268297 |
+ }
|
|
|
268297 |
+ close_json_object();
|
|
|
268297 |
+
|
|
|
268297 |
+ return 0;
|
|
|
268297 |
+
|
|
|
268297 |
+err_close_stats:
|
|
|
268297 |
+ close_json_object();
|
|
|
268297 |
+ return -1;
|
|
|
268297 |
+}
|
|
|
268297 |
+
|
|
|
268297 |
int pause_reply_cb(const struct nlmsghdr *nlhdr, void *data)
|
|
|
268297 |
{
|
|
|
268297 |
const struct nlattr *tb[ETHTOOL_A_PAUSE_MAX + 1] = {};
|
|
|
268297 |
@@ -142,6 +199,11 @@ int pause_reply_cb(const struct nlmsghdr *nlhdr, void *data)
|
|
|
268297 |
if (ret < 0)
|
|
|
268297 |
goto err_close_dev;
|
|
|
268297 |
}
|
|
|
268297 |
+ if (tb[ETHTOOL_A_PAUSE_STATS]) {
|
|
|
268297 |
+ ret = show_pause_stats(tb[ETHTOOL_A_PAUSE_STATS]);
|
|
|
268297 |
+ if (ret < 0)
|
|
|
268297 |
+ goto err_close_dev;
|
|
|
268297 |
+ }
|
|
|
268297 |
if (!silent)
|
|
|
268297 |
print_nl();
|
|
|
268297 |
|
|
|
268297 |
@@ -158,6 +220,7 @@ int nl_gpause(struct cmd_context *ctx)
|
|
|
268297 |
{
|
|
|
268297 |
struct nl_context *nlctx = ctx->nlctx;
|
|
|
268297 |
struct nl_socket *nlsk = nlctx->ethnl_socket;
|
|
|
268297 |
+ u32 flags;
|
|
|
268297 |
int ret;
|
|
|
268297 |
|
|
|
268297 |
if (netlink_cmd_check(ctx, ETHTOOL_MSG_PAUSE_GET, true))
|
|
|
268297 |
@@ -168,8 +231,10 @@ int nl_gpause(struct cmd_context *ctx)
|
|
|
268297 |
return 1;
|
|
|
268297 |
}
|
|
|
268297 |
|
|
|
268297 |
+ flags = get_stats_flag(nlctx, ETHTOOL_MSG_PAUSE_GET,
|
|
|
268297 |
+ ETHTOOL_A_PAUSE_HEADER);
|
|
|
268297 |
ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_PAUSE_GET,
|
|
|
268297 |
- ETHTOOL_A_PAUSE_HEADER, 0);
|
|
|
268297 |
+ ETHTOOL_A_PAUSE_HEADER, flags);
|
|
|
268297 |
if (ret < 0)
|
|
|
268297 |
return ret;
|
|
|
268297 |
|
|
|
268297 |
--
|
|
|
268297 |
2.26.2
|
|
|
268297 |
|