@@ -240,7 +240,7 @@ ethtool \- query or control network driver and hardware settings
.HP
.B ethtool \-S|\-\-statistics
.I devname
-.RB [\fB\-\-groups
+.RB [\fB\-\-all\-groups\fP|\fB\-\-groups
.RB [\fBeth\-phy\fP]
.RB [\fBeth\-mac\fP]
.RB [\fBeth\-ctrl\fP]
@@ -667,6 +667,9 @@ devices may implement either, both or none. There is little commonality between
naming of NIC- and driver-specific statistics across vendors.
.RS 4
.TP
+.B \fB\-\-all\-groups
+.E
+.TP
.B \fB\-\-groups [\fBeth\-phy\fP] [\fBeth\-mac\fP] [\fBeth\-ctrl\fP] [\fBrmon\fP]
Request groups of standard device statistics.
.RE
@@ -5776,7 +5776,7 @@ static const struct option args[] = {
.nlchk = nl_gstats_chk,
.nlfunc = nl_gstats,
.help = "Show adapter statistics",
- .xhelp = " [ --groups [eth-phy] [eth-mac] [eth-ctrl] [rmon] ]\n"
+ .xhelp = " [ --all-groups | --groups [eth-phy] [eth-mac] [eth-ctrl] [rmon] ]\n"
},
{
.opts = "--phy-statistics",
@@ -919,6 +919,17 @@ static void __parser_set(uint64_t *map, unsigned int idx)
map[idx / 64] |= (1 << (idx % 64));
}
+static void __parser_set_group(const struct param_parser *params,
+ uint64_t *map, unsigned int alt_group)
+{
+ const struct param_parser *parser;
+ unsigned int idx = 0;
+
+ for (parser = params; parser->arg; parser++, idx++)
+ if (parser->alt_group == alt_group)
+ __parser_set(map, idx);
+}
+
struct tmp_buff {
struct nl_msg_buff *msgbuff;
unsigned int id;
@@ -1074,7 +1085,11 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
parser_err_min_argc(nlctx, parser->min_argc);
goto out_free;
}
- __parser_set(params_seen, parser - params);
+ if (parser->alt_group)
+ __parser_set_group(params, params_seen,
+ parser->alt_group);
+ else
+ __parser_set(params_seen, parser - params);
buff = NULL;
if (parser->group)
@@ -43,6 +43,10 @@ struct param_parser {
unsigned int min_argc;
/* if @dest is passed to nl_parser(), offset to store value */
unsigned int dest_offset;
+ /* parameter alternative group - only one parameter from a group
+ * can be specified, 0 means no group
+ */
+ unsigned int alt_group;
};
/* data structures used for handler data */
@@ -220,6 +220,54 @@ static const struct bitset_parser_data stats_parser_data = {
.force_hex = false,
};
+static int stats_parse_all_groups(struct nl_context *nlctx, uint16_t type,
+ const void *data, struct nl_msg_buff *msgbuff,
+ void *dest)
+{
+ const struct stringset *std_str;
+ struct nlattr *nest;
+ int i, ret, nbits;
+ uint32_t *bits;
+
+ if (data || dest)
+ return -EFAULT;
+
+ /* ethnl2 and strset code already does caching */
+ ret = netlink_init_ethnl2_socket(nlctx);
+ if (ret < 0)
+ return ret;
+ std_str = global_stringset(ETH_SS_STATS_STD, nlctx->ethnl2_socket);
+
+ nbits = get_count(std_str);
+ bits = calloc(DIV_ROUND_UP(nbits, 32), sizeof(uint32_t));
+ if (!bits)
+ return -ENOMEM;
+
+ for (i = 0; i < nbits; i++)
+ bits[i / 32] |= 1U << (i % 32);
+
+ ret = -EMSGSIZE;
+ nest = ethnla_nest_start(msgbuff, type);
+ if (!nest)
+ goto err_free;
+
+ if (ethnla_put_flag(msgbuff, ETHTOOL_A_BITSET_NOMASK, true) ||
+ ethnla_put_u32(msgbuff, ETHTOOL_A_BITSET_SIZE, nbits) ||
+ ethnla_put(msgbuff, ETHTOOL_A_BITSET_VALUE,
+ DIV_ROUND_UP(nbits, 32) * sizeof(uint32_t), bits))
+ goto err_cancel;
+
+ ethnla_nest_end(msgbuff, nest);
+ free(bits);
+ return 0;
+
+err_cancel:
+ ethnla_nest_cancel(msgbuff, nest);
+err_free:
+ free(bits);
+ return ret;
+}
+
static const struct param_parser stats_params[] = {
{
.arg = "--groups",
@@ -227,6 +275,13 @@ static const struct param_parser stats_params[] = {
.handler = nl_parse_bitset,
.handler_data = &stats_parser_data,
.min_argc = 1,
+ .alt_group = 1,
+ },
+ {
+ .arg = "--all-groups",
+ .type = ETHTOOL_A_STATS_GROUPS,
+ .handler = stats_parse_all_groups,
+ .alt_group = 1,
},
{}
};