^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include "netlink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "bitset.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) struct debug_req_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) struct ethnl_req_info base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct debug_reply_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) struct ethnl_reply_data base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) u32 msg_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define DEBUG_REPDATA(__reply_base) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) container_of(__reply_base, struct debug_reply_data, base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) const struct nla_policy ethnl_debug_get_policy[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) [ETHTOOL_A_DEBUG_HEADER] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) NLA_POLICY_NESTED(ethnl_header_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static int debug_prepare_data(const struct ethnl_req_info *req_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct ethnl_reply_data *reply_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct net_device *dev = reply_base->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (!dev->ethtool_ops->get_msglevel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ret = ethnl_ops_begin(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) data->msg_mask = dev->ethtool_ops->get_msglevel(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ethnl_ops_complete(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int debug_reply_size(const struct ethnl_req_info *req_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) const struct ethnl_reply_data *reply_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) const struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return ethnl_bitset32_size(&data->msg_mask, NULL, NETIF_MSG_CLASS_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) netif_msg_class_names, compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static int debug_fill_reply(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) const struct ethnl_req_info *req_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const struct ethnl_reply_data *reply_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) const struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return ethnl_put_bitset32(skb, ETHTOOL_A_DEBUG_MSGMASK, &data->msg_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) NULL, NETIF_MSG_CLASS_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) netif_msg_class_names, compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) const struct ethnl_request_ops ethnl_debug_request_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .request_cmd = ETHTOOL_MSG_DEBUG_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .reply_cmd = ETHTOOL_MSG_DEBUG_GET_REPLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .hdr_attr = ETHTOOL_A_DEBUG_HEADER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .req_info_size = sizeof(struct debug_req_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .reply_data_size = sizeof(struct debug_reply_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .prepare_data = debug_prepare_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .reply_size = debug_reply_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .fill_reply = debug_fill_reply,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* DEBUG_SET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) const struct nla_policy ethnl_debug_set_policy[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) [ETHTOOL_A_DEBUG_HEADER] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) NLA_POLICY_NESTED(ethnl_header_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) [ETHTOOL_A_DEBUG_MSGMASK] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct ethnl_req_info req_info = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct nlattr **tb = info->attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) bool mod = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 msg_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ret = ethnl_parse_header_dev_get(&req_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) tb[ETHTOOL_A_DEBUG_HEADER],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) genl_info_net(info), info->extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) dev = req_info.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (!dev->ethtool_ops->get_msglevel || !dev->ethtool_ops->set_msglevel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) goto out_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ret = ethnl_ops_begin(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) goto out_rtnl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) msg_mask = dev->ethtool_ops->get_msglevel(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ret = ethnl_update_bitset32(&msg_mask, NETIF_MSG_CLASS_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) tb[ETHTOOL_A_DEBUG_MSGMASK],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) netif_msg_class_names, info->extack, &mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (ret < 0 || !mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) goto out_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) dev->ethtool_ops->set_msglevel(dev, msg_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ethtool_notify(dev, ETHTOOL_MSG_DEBUG_NTF, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) out_ops:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ethnl_ops_complete(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) out_rtnl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) out_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }