From patchwork Thu Dec 29 01:12:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Mogilappagari, Sudheer" X-Patchwork-Id: 13083246 X-Patchwork-Delegate: mkubecek+ethtool@suse.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64FD2C3DA7C for ; Thu, 29 Dec 2022 01:17:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232463AbiL2BRj (ORCPT ); Wed, 28 Dec 2022 20:17:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59814 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231183AbiL2BRh (ORCPT ); Wed, 28 Dec 2022 20:17:37 -0500 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1E5A713F57 for ; Wed, 28 Dec 2022 17:17:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1672276657; x=1703812657; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=E5572UmhR2mQ3TfvYt3z2iojIxg2RNneWwjwuQU2P5g=; b=m77fSw0kv6qXuC4WmxnN2Op5Oq199oktRoBULSyKscWn5sc50GGIoBdR CV5+4NIP+olBfKVd5N3GJIli0ZBNQaTPHygdEHULYjhDl7JBoF8x/EnUG 5MlbUpXcn8eSr/BoQJyGQS9Z9WI0rjzQibNQme2LAlwjvjU0nnUlPJc7b T1axFBFH7Nx3OCAon3JH3i6sosK/pLoWurG/tNTkdQNI/kqtodPjH+qbI AxseWdXURcMnikFOLl7OrNyJiNndwnnqLbLT1DKDHCtInhWAkN26KKSU2 fMm15Janvgcsv11wsz6Un1lqKqlKmps56Y7f4MWhjA1Cr8tdU4Pg06mLQ Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10574"; a="301326144" X-IronPort-AV: E=Sophos;i="5.96,282,1665471600"; d="scan'208";a="301326144" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Dec 2022 17:17:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10574"; a="653468118" X-IronPort-AV: E=Sophos;i="5.96,282,1665471600"; d="scan'208";a="653468118" Received: from msu-dell.jf.intel.com ([10.166.233.5]) by orsmga002.jf.intel.com with ESMTP; 28 Dec 2022 17:17:35 -0800 From: Sudheer Mogilappagari To: netdev@vger.kernel.org Cc: kuba@kernel.org, mkubecek@suse.cz, andrew@lunn.ch, sridhar.samudrala@intel.com, anthony.l.nguyen@intel.com Subject: [PATCH ethtool-next v4 1/2] Move code that print rss info into common file Date: Wed, 28 Dec 2022 17:12:42 -0800 Message-Id: <20221229011243.1527945-2-sudheer.mogilappagari@intel.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20221229011243.1527945-1-sudheer.mogilappagari@intel.com> References: <20221229011243.1527945-1-sudheer.mogilappagari@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: mkubecek+ethtool@suse.cz Move functions that prints rss indirection table and hash key into common file for use by both netlink and ioctl interface. Changed function argument to be ring count instead of structure. Signed-off-by: Sudheer Mogilappagari --- common.c | 43 +++++++++++++++++++++++++++++++++++++++++++ common.h | 7 +++++++ ethtool.c | 44 ++++---------------------------------------- 3 files changed, 54 insertions(+), 40 deletions(-) diff --git a/common.c b/common.c index 2630e73..0f2d8c0 100644 --- a/common.c +++ b/common.c @@ -173,3 +173,46 @@ void dump_mdix(u8 mdix, u8 mdix_ctrl) fprintf(stdout, "\n"); } } + +void print_indir_table(struct cmd_context *ctx, u64 ring_count, + u32 indir_size, u32 *indir) +{ + u32 i; + + printf("RX flow hash indirection table for %s with %llu RX ring(s):\n", + ctx->devname, ring_count); + + if (!indir_size) + printf("Operation not supported\n"); + + for (i = 0; i < indir_size; i++) { + if (i % 8 == 0) + printf("%5u: ", i); + printf(" %5u", indir[i]); + if (i % 8 == 7 || i == indir_size - 1) + fputc('\n', stdout); + } +} + +void print_rss_info(struct cmd_context *ctx, u64 ring_count, + struct ethtool_rxfh *rss) +{ + u32 i, indir_bytes; + char *hkey; + + print_indir_table(ctx, ring_count, rss->indir_size, rss->rss_config); + + indir_bytes = rss->indir_size * sizeof(rss->rss_config[0]); + hkey = ((char *)rss->rss_config + indir_bytes); + + printf("RSS hash key:\n"); + if (!rss->key_size) + printf("Operation not supported\n"); + + for (i = 0; i < rss->key_size; i++) { + if (i == (rss->key_size - 1)) + printf("%02x\n", (u8)hkey[i]); + else + printf("%02x:", (u8)hkey[i]); + } +} diff --git a/common.h b/common.h index b74fdfa..8589714 100644 --- a/common.h +++ b/common.h @@ -8,6 +8,8 @@ #define ETHTOOL_COMMON_H__ #include "internal.h" +#include +#include #define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) @@ -41,5 +43,10 @@ extern const struct off_flag_def off_flag_def[OFF_FLAG_DEF_SIZE]; void print_flags(const struct flag_info *info, unsigned int n_info, u32 value); int dump_wol(struct ethtool_wolinfo *wol); void dump_mdix(u8 mdix, u8 mdix_ctrl); +void print_indir_table(struct cmd_context *ctx, u64 ring_count, + u32 indir_size, u32 *indir); + +void print_rss_info(struct cmd_context *ctx, u64 ring_count, + struct ethtool_rxfh *rss); #endif /* ETHTOOL_COMMON_H__ */ diff --git a/ethtool.c b/ethtool.c index 60da8af..209dbd1 100644 --- a/ethtool.c +++ b/ethtool.c @@ -3900,27 +3900,6 @@ static int do_grxclass(struct cmd_context *ctx) return err ? 1 : 0; } -static void print_indir_table(struct cmd_context *ctx, - struct ethtool_rxnfc *ring_count, - u32 indir_size, u32 *indir) -{ - u32 i; - - printf("RX flow hash indirection table for %s with %llu RX ring(s):\n", - ctx->devname, ring_count->data); - - if (!indir_size) - printf("Operation not supported\n"); - - for (i = 0; i < indir_size; i++) { - if (i % 8 == 0) - printf("%5u: ", i); - printf(" %5u", indir[i]); - if (i % 8 == 7 || i == indir_size - 1) - fputc('\n', stdout); - } -} - static int do_grxfhindir(struct cmd_context *ctx, struct ethtool_rxnfc *ring_count) { @@ -3952,7 +3931,8 @@ static int do_grxfhindir(struct cmd_context *ctx, return 1; } - print_indir_table(ctx, ring_count, indir->size, indir->ring_index); + print_indir_table(ctx, ring_count->data, indir->size, + indir->ring_index); free(indir); return 0; @@ -3965,9 +3945,7 @@ static int do_grxfh(struct cmd_context *ctx) struct ethtool_rxnfc ring_count; struct ethtool_rxfh *rss; u32 rss_context = 0; - u32 i, indir_bytes; - unsigned int arg_num = 0; - char *hkey; + unsigned int arg_num = 0, i; int err; while (arg_num < ctx->argc) { @@ -4017,21 +3995,7 @@ static int do_grxfh(struct cmd_context *ctx) return 1; } - print_indir_table(ctx, &ring_count, rss->indir_size, rss->rss_config); - - indir_bytes = rss->indir_size * sizeof(rss->rss_config[0]); - hkey = ((char *)rss->rss_config + indir_bytes); - - printf("RSS hash key:\n"); - if (!rss->key_size) - printf("Operation not supported\n"); - - for (i = 0; i < rss->key_size; i++) { - if (i == (rss->key_size - 1)) - printf("%02x\n", (u8) hkey[i]); - else - printf("%02x:", (u8) hkey[i]); - } + print_rss_info(ctx, ring_count.data, rss); printf("RSS hash function:\n"); if (!rss->hfunc) { From patchwork Thu Dec 29 01:12:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Mogilappagari, Sudheer" X-Patchwork-Id: 13083247 X-Patchwork-Delegate: mkubecek+ethtool@suse.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54600C4332F for ; Thu, 29 Dec 2022 01:17:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232066AbiL2BRl (ORCPT ); Wed, 28 Dec 2022 20:17:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59816 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231722AbiL2BRi (ORCPT ); Wed, 28 Dec 2022 20:17:38 -0500 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3E29213F5E for ; Wed, 28 Dec 2022 17:17:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1672276657; x=1703812657; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8s1PPTpe87ilp9rm0oxwNV5XoErCvojtNnQEABAtMaE=; b=fDJKbQXuEOF3F/A56Jl5E4/CL8TGXY5Rub5/CTaKXzu2KIZfoH2xI1XL YGDCLvUkqoi+ZRc7x4cAzWLDZNG2B25AjYQBtJsNIlnOpOvfsU2RlALpD SSmEyiVttdecUWG0SDcb0JiAYcdV+s1xJpGCFVWEiQh5ToJDx2d0uo6/L i3QHbXYP5WfzX039fitOqsUoIj9z0CuxVINMlw0J4B03ee3hEcqdTbsWg WTcXt2tbjkDQfDFIplSsBlWYUUKNcWGi8DZCu22NIpkPgPsjyl2ifprm1 qJdpdKUAVsfBzwuuux0Wtxhe9RCljRhi498qk/mypQIQGyQxzGJSrHtfa Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10574"; a="301326145" X-IronPort-AV: E=Sophos;i="5.96,282,1665471600"; d="scan'208";a="301326145" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Dec 2022 17:17:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10574"; a="653468122" X-IronPort-AV: E=Sophos;i="5.96,282,1665471600"; d="scan'208";a="653468122" Received: from msu-dell.jf.intel.com ([10.166.233.5]) by orsmga002.jf.intel.com with ESMTP; 28 Dec 2022 17:17:35 -0800 From: Sudheer Mogilappagari To: netdev@vger.kernel.org Cc: kuba@kernel.org, mkubecek@suse.cz, andrew@lunn.ch, sridhar.samudrala@intel.com, anthony.l.nguyen@intel.com Subject: [PATCH ethtool-next v4 2/2] netlink: add netlink handler for get rss (-x) Date: Wed, 28 Dec 2022 17:12:43 -0800 Message-Id: <20221229011243.1527945-3-sudheer.mogilappagari@intel.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20221229011243.1527945-1-sudheer.mogilappagari@intel.com> References: <20221229011243.1527945-1-sudheer.mogilappagari@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: mkubecek+ethtool@suse.cz Add support for netlink based "ethtool -x " command using ETHTOOL_MSG_RSS_GET netlink message. It implements same functionality provided by traditional ETHTOOL_GRSSH subcommand. This displays RSS table, hash key and hash function along with JSON support. Sample output with json option: $ethtool --json -x eno2 [ { "ifname": "eno2", "rss-indirection-table": [ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1, ...skip similar lines... 7,7,7,7,7,7,7,7 ], "rss-hash-key": [ 190,195,19,166,..] "rss-hash-function": { "toeplitz": true, "xor": false, "crc32": false } } ] Signed-off-by: Sudheer Mogilappagari --- Makefile.am | 2 +- ethtool.c | 2 + netlink/desc-ethtool.c | 11 ++ netlink/extapi.h | 2 + netlink/rss.c | 241 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 netlink/rss.c diff --git a/Makefile.am b/Makefile.am index 663f40a..c3e7401 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,7 +39,7 @@ ethtool_SOURCES += \ netlink/eee.c netlink/tsinfo.c netlink/fec.c \ netlink/stats.c \ netlink/desc-ethtool.c netlink/desc-genlctrl.c \ - netlink/module-eeprom.c netlink/module.c \ + netlink/module-eeprom.c netlink/module.c netlink/rss.c \ netlink/desc-rtnl.c netlink/cable_test.c netlink/tunnels.c \ uapi/linux/ethtool_netlink.h \ uapi/linux/netlink.h uapi/linux/genetlink.h \ diff --git a/ethtool.c b/ethtool.c index 209dbd1..5c16b10 100644 --- a/ethtool.c +++ b/ethtool.c @@ -5850,7 +5850,9 @@ static const struct option args[] = { }, { .opts = "-x|--show-rxfh-indir|--show-rxfh", + .json = true, .func = do_grxfh, + .nlfunc = nl_grss, .help = "Show Rx flow hash indirection table and/or RSS hash key", .xhelp = " [ context %d ]\n" }, diff --git a/netlink/desc-ethtool.c b/netlink/desc-ethtool.c index b3ac64d..ed83dae 100644 --- a/netlink/desc-ethtool.c +++ b/netlink/desc-ethtool.c @@ -442,6 +442,15 @@ static const struct pretty_nla_desc __pse_desc[] = { NLATTR_DESC_U32_ENUM(ETHTOOL_A_PODL_PSE_PW_D_STATUS, pse_pw_d_status), }; +static const struct pretty_nla_desc __rss_desc[] = { + NLATTR_DESC_INVALID(ETHTOOL_A_MODULE_UNSPEC), + NLATTR_DESC_NESTED(ETHTOOL_A_MODULE_HEADER, header), + NLATTR_DESC_U32(ETHTOOL_A_RSS_CONTEXT), + NLATTR_DESC_U32(ETHTOOL_A_RSS_HFUNC), + NLATTR_DESC_BINARY(ETHTOOL_A_RSS_INDIR), + NLATTR_DESC_BINARY(ETHTOOL_A_RSS_HKEY), +}; + const struct pretty_nlmsg_desc ethnl_umsg_desc[] = { NLMSG_DESC_INVALID(ETHTOOL_MSG_USER_NONE), NLMSG_DESC(ETHTOOL_MSG_STRSET_GET, strset), @@ -481,6 +490,7 @@ const struct pretty_nlmsg_desc ethnl_umsg_desc[] = { NLMSG_DESC(ETHTOOL_MSG_MODULE_SET, module), NLMSG_DESC(ETHTOOL_MSG_PSE_GET, pse), NLMSG_DESC(ETHTOOL_MSG_PSE_SET, pse), + NLMSG_DESC(ETHTOOL_MSG_RSS_GET, rss), }; const unsigned int ethnl_umsg_n_desc = ARRAY_SIZE(ethnl_umsg_desc); @@ -524,6 +534,7 @@ const struct pretty_nlmsg_desc ethnl_kmsg_desc[] = { NLMSG_DESC(ETHTOOL_MSG_MODULE_GET_REPLY, module), NLMSG_DESC(ETHTOOL_MSG_MODULE_NTF, module), NLMSG_DESC(ETHTOOL_MSG_PSE_GET_REPLY, pse), + NLMSG_DESC(ETHTOOL_MSG_RSS_GET_REPLY, rss), }; const unsigned int ethnl_kmsg_n_desc = ARRAY_SIZE(ethnl_kmsg_desc); diff --git a/netlink/extapi.h b/netlink/extapi.h index 1bb580a..9b6dd1a 100644 --- a/netlink/extapi.h +++ b/netlink/extapi.h @@ -47,6 +47,7 @@ int nl_gmodule(struct cmd_context *ctx); int nl_smodule(struct cmd_context *ctx); int nl_monitor(struct cmd_context *ctx); int nl_getmodule(struct cmd_context *ctx); +int nl_grss(struct cmd_context *ctx); void nl_monitor_usage(void); @@ -114,6 +115,7 @@ nl_get_eeprom_page(struct cmd_context *ctx __maybe_unused, #define nl_getmodule NULL #define nl_gmodule NULL #define nl_smodule NULL +#define nl_grss NULL #endif /* ETHTOOL_ENABLE_NETLINK */ diff --git a/netlink/rss.c b/netlink/rss.c new file mode 100644 index 0000000..f52c2e7 --- /dev/null +++ b/netlink/rss.c @@ -0,0 +1,241 @@ +/* + * rss.c - netlink implementation of RSS context commands + * + * Implementation of "ethtool -x " + */ + +#include +#include +#include + +#include "../internal.h" +#include "../common.h" +#include "netlink.h" +#include "strset.h" +#include "parser.h" + +struct cb_args { + struct nl_context *nlctx; + u32 num_rings; +}; + +void dump_json_rss_info(struct cmd_context *ctx, struct ethtool_rxfh *rss, + const struct stringset *hash_funcs) +{ + unsigned int indir_bytes = rss->indir_size * sizeof(rss->rss_config[0]); + unsigned int i; + + open_json_object(NULL); + print_string(PRINT_JSON, "ifname", NULL, ctx->devname); + if (rss->indir_size) { + open_json_array("rss-indirection-table", NULL); + for (i = 0; i < rss->indir_size; i++) + print_uint(PRINT_JSON, NULL, NULL, rss->rss_config[i]); + close_json_array("\n"); + } + + if (rss->key_size) { + const char *hkey = ((char *)rss->rss_config + indir_bytes); + + open_json_array("rss-hash-key", NULL); + for (i = 0; i < rss->key_size; i++) + print_uint(PRINT_JSON, NULL, NULL, (u8)hkey[i]); + close_json_array("\n"); + } + + if (rss->hfunc) { + open_json_object("rss-hash-function"); + for (i = 0; i < get_count(hash_funcs); i++) + print_bool(PRINT_JSON, get_string(hash_funcs, i), NULL, + (rss->hfunc & (1 << i))); + close_json_object(); + } + + close_json_object(); +} + +int rss_reply_cb(const struct nlmsghdr *nlhdr, void *data) +{ + const struct nlattr *tb[ETHTOOL_A_RSS_MAX + 1] = {}; + unsigned int indir_bytes = 0, hkey_bytes = 0; + DECLARE_ATTR_TB_INFO(tb); + struct cb_args *args = data; + struct nl_context *nlctx = args->nlctx; + const struct stringset *hash_funcs; + u32 rss_config_size, rss_hfunc; + const char *indir_table, *hkey; + + struct ethtool_rxfh *rss; + bool silent; + int err_ret; + int ret; + + silent = nlctx->is_dump || nlctx->is_monitor; + err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR; + ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info); + if (ret < 0) + return err_ret; + nlctx->devname = get_dev_name(tb[ETHTOOL_A_RSS_HEADER]); + if (!dev_ok(nlctx)) + return err_ret; + + if (silent) + putchar('\n'); + + rss_hfunc = mnl_attr_get_u32(tb[ETHTOOL_A_RSS_HFUNC]); + + indir_bytes = mnl_attr_get_payload_len(tb[ETHTOOL_A_RSS_INDIR]); + indir_table = mnl_attr_get_str(tb[ETHTOOL_A_RSS_INDIR]); + + hkey_bytes = mnl_attr_get_payload_len(tb[ETHTOOL_A_RSS_HKEY]); + hkey = mnl_attr_get_str(tb[ETHTOOL_A_RSS_HKEY]); + + rss_config_size = indir_bytes + hkey_bytes; + + rss = calloc(1, sizeof(*rss) + rss_config_size); + if (!rss) { + perror("Cannot allocate memory for RX flow hash config"); + return 1; + } + + rss->indir_size = indir_bytes / sizeof(rss->rss_config[0]); + rss->key_size = hkey_bytes; + rss->hfunc = rss_hfunc; + + memcpy(rss->rss_config, indir_table, indir_bytes); + memcpy(rss->rss_config + rss->indir_size, hkey, hkey_bytes); + + /* Fetch RSS hash functions and their status and print */ + + if (!nlctx->is_monitor) { + ret = netlink_init_ethnl2_socket(nlctx); + if (ret < 0) + return MNL_CB_ERROR; + } + hash_funcs = global_stringset(ETH_SS_RSS_HASH_FUNCS, + nlctx->ethnl2_socket); + + ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info); + if (ret < 0) + return silent ? MNL_CB_OK : MNL_CB_ERROR; + nlctx->devname = get_dev_name(tb[ETHTOOL_A_RSS_HEADER]); + if (!dev_ok(nlctx)) + return MNL_CB_OK; + + if (is_json_context()) { + dump_json_rss_info(nlctx->ctx, rss, hash_funcs); + } else { + print_rss_info(nlctx->ctx, args->num_rings, rss); + printf("RSS hash function:\n"); + if (!rss_hfunc) { + printf(" Operation not supported\n"); + return 0; + } + for (unsigned int i = 0; i < get_count(hash_funcs); i++) { + printf(" %s: %s\n", get_string(hash_funcs, i), + (rss_hfunc & (1 << i)) ? "on" : "off"); + } + } + + free(rss); + return MNL_CB_OK; +} + +/* RSS_GET */ +static const struct param_parser grss_params[] = { + { + .arg = "context", + .type = ETHTOOL_A_RSS_CONTEXT, + .handler = nl_parse_direct_u32, + .min_argc = 1, + }, + {} +}; + +int get_channels_cb(const struct nlmsghdr *nlhdr, void *data) +{ + const struct nlattr *tb[ETHTOOL_A_CHANNELS_MAX + 1] = {}; + DECLARE_ATTR_TB_INFO(tb); + struct cb_args *args = data; + struct nl_context *nlctx = args->nlctx; + bool silent; + int err_ret; + int ret; + + silent = nlctx->is_dump || nlctx->is_monitor; + err_ret = silent ? MNL_CB_OK : MNL_CB_ERROR; + ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info); + if (ret < 0) + return err_ret; + nlctx->devname = get_dev_name(tb[ETHTOOL_A_CHANNELS_HEADER]); + if (!dev_ok(nlctx)) + return err_ret; + + args->num_rings = mnl_attr_get_u8(tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT]); + return MNL_CB_OK; +} + +int nl_grss(struct cmd_context *ctx) +{ + struct nl_context *nlctx = ctx->nlctx; + struct nl_socket *nlsk = nlctx->ethnl_socket; + struct nl_msg_buff *msgbuff; + struct cb_args args; + int ret; + + nlctx->cmd = "-x"; + nlctx->argp = ctx->argp; + nlctx->argc = ctx->argc; + nlctx->devname = ctx->devname; + nlsk = nlctx->ethnl_socket; + msgbuff = &nlsk->msgbuff; + + if (netlink_cmd_check(ctx, ETHTOOL_MSG_RSS_GET, true)) + return -EOPNOTSUPP; + + /* save rings information into args.num_rings */ + if (netlink_cmd_check(ctx, ETHTOOL_MSG_CHANNELS_GET, true)) + return -EOPNOTSUPP; + + ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_CHANNELS_GET, + ETHTOOL_A_CHANNELS_HEADER, 0); + if (ret < 0) + goto err; + + ret = nlsock_sendmsg(nlsk, NULL); + if (ret < 0) + goto err; + + args.nlctx = nlsk->nlctx; + ret = nlsock_process_reply(nlsk, get_channels_cb, &args); + if (ret < 0) + goto err; + + ret = msg_init(nlctx, msgbuff, ETHTOOL_MSG_RSS_GET, + NLM_F_REQUEST | NLM_F_ACK); + if (ret < 0) + return 1; + if (ethnla_fill_header(msgbuff, ETHTOOL_A_RSS_HEADER, + ctx->devname, 0)) + return -EMSGSIZE; + + ret = nl_parser(nlctx, grss_params, NULL, PARSER_GROUP_NONE, NULL); + if (ret < 0) + goto err; + + new_json_obj(ctx->json); + ret = nlsock_sendmsg(nlsk, NULL); + if (ret < 0) + goto err; + + args.nlctx = nlctx; + ret = nlsock_process_reply(nlsk, rss_reply_cb, &args); + delete_json_obj(); + + if (ret == 0) + return 0; + +err: + return nlctx->exit_code ?: 1; +} +