ethtool: provide message mask with DEBUG_GET request

Implement DEBUG_GET request to get debugging settings for a device. At the
moment, only message mask corresponding to message level as reported by
ETHTOOL_GMSGLVL ioctl request is provided. (It is called message level in
ioctl interface but almost all drivers interpret it as a bit mask.)

As part of the implementation, provide symbolic names for message mask bits
as ETH_SS_MSG_CLASSES string set.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Michal Kubecek
2020-01-26 23:11:04 +01:00
committed by David S. Miller
parent d2c4b444fd
commit 6a94b8ccf6
11 changed files with 205 additions and 17 deletions

View File

@@ -5,4 +5,4 @@ obj-y += ioctl.o common.o
obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o
ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o \
linkstate.o
linkstate.o debug.o

View File

@@ -171,6 +171,25 @@ const char link_mode_names[][ETH_GSTRING_LEN] = {
};
static_assert(ARRAY_SIZE(link_mode_names) == __ETHTOOL_LINK_MODE_MASK_NBITS);
const char netif_msg_class_names[][ETH_GSTRING_LEN] = {
[NETIF_MSG_DRV_BIT] = "drv",
[NETIF_MSG_PROBE_BIT] = "probe",
[NETIF_MSG_LINK_BIT] = "link",
[NETIF_MSG_TIMER_BIT] = "timer",
[NETIF_MSG_IFDOWN_BIT] = "ifdown",
[NETIF_MSG_IFUP_BIT] = "ifup",
[NETIF_MSG_RX_ERR_BIT] = "rx_err",
[NETIF_MSG_TX_ERR_BIT] = "tx_err",
[NETIF_MSG_TX_QUEUED_BIT] = "tx_queued",
[NETIF_MSG_INTR_BIT] = "intr",
[NETIF_MSG_TX_DONE_BIT] = "tx_done",
[NETIF_MSG_RX_STATUS_BIT] = "rx_status",
[NETIF_MSG_PKTDATA_BIT] = "pktdata",
[NETIF_MSG_HW_BIT] = "hw",
[NETIF_MSG_WOL_BIT] = "wol",
};
static_assert(ARRAY_SIZE(netif_msg_class_names) == NETIF_MSG_CLASS_COUNT);
/* return false if legacy contained non-0 deprecated fields
* maxtxpkt/maxrxpkt. rest of ksettings always updated
*/

View File

@@ -19,6 +19,7 @@ tunable_strings[__ETHTOOL_TUNABLE_COUNT][ETH_GSTRING_LEN];
extern const char
phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN];
extern const char link_mode_names[][ETH_GSTRING_LEN];
extern const char netif_msg_class_names[][ETH_GSTRING_LEN];
int __ethtool_get_link(struct net_device *dev);

80
net/ethtool/debug.c Normal file
View File

@@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0-only
#include "netlink.h"
#include "common.h"
#include "bitset.h"
struct debug_req_info {
struct ethnl_req_info base;
};
struct debug_reply_data {
struct ethnl_reply_data base;
u32 msg_mask;
};
#define DEBUG_REPDATA(__reply_base) \
container_of(__reply_base, struct debug_reply_data, base)
static const struct nla_policy
debug_get_policy[ETHTOOL_A_DEBUG_MAX + 1] = {
[ETHTOOL_A_DEBUG_UNSPEC] = { .type = NLA_REJECT },
[ETHTOOL_A_DEBUG_HEADER] = { .type = NLA_NESTED },
[ETHTOOL_A_DEBUG_MSGMASK] = { .type = NLA_REJECT },
};
static int debug_prepare_data(const struct ethnl_req_info *req_base,
struct ethnl_reply_data *reply_base,
struct genl_info *info)
{
struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
struct net_device *dev = reply_base->dev;
int ret;
if (!dev->ethtool_ops->get_msglevel)
return -EOPNOTSUPP;
ret = ethnl_ops_begin(dev);
if (ret < 0)
return ret;
data->msg_mask = dev->ethtool_ops->get_msglevel(dev);
ethnl_ops_complete(dev);
return 0;
}
static int debug_reply_size(const struct ethnl_req_info *req_base,
const struct ethnl_reply_data *reply_base)
{
const struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
return ethnl_bitset32_size(&data->msg_mask, NULL, NETIF_MSG_CLASS_COUNT,
netif_msg_class_names, compact);
}
static int debug_fill_reply(struct sk_buff *skb,
const struct ethnl_req_info *req_base,
const struct ethnl_reply_data *reply_base)
{
const struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
return ethnl_put_bitset32(skb, ETHTOOL_A_DEBUG_MSGMASK, &data->msg_mask,
NULL, NETIF_MSG_CLASS_COUNT,
netif_msg_class_names, compact);
}
const struct ethnl_request_ops ethnl_debug_request_ops = {
.request_cmd = ETHTOOL_MSG_DEBUG_GET,
.reply_cmd = ETHTOOL_MSG_DEBUG_GET_REPLY,
.hdr_attr = ETHTOOL_A_DEBUG_HEADER,
.max_attr = ETHTOOL_A_DEBUG_MAX,
.req_info_size = sizeof(struct debug_req_info),
.reply_data_size = sizeof(struct debug_reply_data),
.request_policy = debug_get_policy,
.prepare_data = debug_prepare_data,
.reply_size = debug_reply_size,
.fill_reply = debug_fill_reply,
};

View File

@@ -213,6 +213,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
[ETHTOOL_MSG_LINKINFO_GET] = &ethnl_linkinfo_request_ops,
[ETHTOOL_MSG_LINKMODES_GET] = &ethnl_linkmodes_request_ops,
[ETHTOOL_MSG_LINKSTATE_GET] = &ethnl_linkstate_request_ops,
[ETHTOOL_MSG_DEBUG_GET] = &ethnl_debug_request_ops,
};
static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -664,6 +665,13 @@ static const struct genl_ops ethtool_genl_ops[] = {
.dumpit = ethnl_default_dumpit,
.done = ethnl_default_done,
},
{
.cmd = ETHTOOL_MSG_DEBUG_GET,
.doit = ethnl_default_doit,
.start = ethnl_default_start,
.dumpit = ethnl_default_dumpit,
.done = ethnl_default_done,
},
};
static const struct genl_multicast_group ethtool_nl_mcgrps[] = {

View File

@@ -334,6 +334,7 @@ extern const struct ethnl_request_ops ethnl_strset_request_ops;
extern const struct ethnl_request_ops ethnl_linkinfo_request_ops;
extern const struct ethnl_request_ops ethnl_linkmodes_request_ops;
extern const struct ethnl_request_ops ethnl_linkstate_request_ops;
extern const struct ethnl_request_ops ethnl_debug_request_ops;
int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);

View File

@@ -50,6 +50,11 @@ static const struct strset_info info_template[] = {
.count = __ETHTOOL_LINK_MODE_MASK_NBITS,
.strings = link_mode_names,
},
[ETH_SS_MSG_CLASSES] = {
.per_dev = false,
.count = NETIF_MSG_CLASS_COUNT,
.strings = netif_msg_class_names,
},
};
struct strset_req_info {