diff options
Diffstat (limited to 'net/ethtool')
-rw-r--r-- | net/ethtool/bitset.c | 26 | ||||
-rw-r--r-- | net/ethtool/cabletest.c | 41 | ||||
-rw-r--r-- | net/ethtool/channels.c | 37 | ||||
-rw-r--r-- | net/ethtool/coalesce.c | 45 | ||||
-rw-r--r-- | net/ethtool/common.c | 2 | ||||
-rw-r--r-- | net/ethtool/debug.c | 24 | ||||
-rw-r--r-- | net/ethtool/eee.c | 32 | ||||
-rw-r--r-- | net/ethtool/features.c | 30 | ||||
-rw-r--r-- | net/ethtool/ioctl.c | 67 | ||||
-rw-r--r-- | net/ethtool/linkinfo.c | 30 | ||||
-rw-r--r-- | net/ethtool/linkmodes.c | 34 | ||||
-rw-r--r-- | net/ethtool/linkstate.c | 14 | ||||
-rw-r--r-- | net/ethtool/netlink.c | 124 | ||||
-rw-r--r-- | net/ethtool/netlink.h | 35 | ||||
-rw-r--r-- | net/ethtool/pause.c | 86 | ||||
-rw-r--r-- | net/ethtool/privflags.c | 24 | ||||
-rw-r--r-- | net/ethtool/rings.c | 35 | ||||
-rw-r--r-- | net/ethtool/strset.c | 26 | ||||
-rw-r--r-- | net/ethtool/tsinfo.c | 13 | ||||
-rw-r--r-- | net/ethtool/tunnels.c | 42 | ||||
-rw-r--r-- | net/ethtool/wol.c | 24 |
21 files changed, 355 insertions, 436 deletions
diff --git a/net/ethtool/bitset.c b/net/ethtool/bitset.c index dae7402eaca3..1fb3603d92ad 100644 --- a/net/ethtool/bitset.c +++ b/net/ethtool/bitset.c @@ -302,8 +302,7 @@ nla_put_failure: return -EMSGSIZE; } -static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = { - [ETHTOOL_A_BITSET_UNSPEC] = { .type = NLA_REJECT }, +static const struct nla_policy bitset_policy[] = { [ETHTOOL_A_BITSET_NOMASK] = { .type = NLA_FLAG }, [ETHTOOL_A_BITSET_SIZE] = NLA_POLICY_MAX(NLA_U32, ETHNL_MAX_BITSET_SIZE), @@ -312,8 +311,7 @@ static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = { [ETHTOOL_A_BITSET_MASK] = { .type = NLA_BINARY }, }; -static const struct nla_policy bit_policy[ETHTOOL_A_BITSET_BIT_MAX + 1] = { - [ETHTOOL_A_BITSET_BIT_UNSPEC] = { .type = NLA_REJECT }, +static const struct nla_policy bit_policy[] = { [ETHTOOL_A_BITSET_BIT_INDEX] = { .type = NLA_U32 }, [ETHTOOL_A_BITSET_BIT_NAME] = { .type = NLA_NUL_STRING }, [ETHTOOL_A_BITSET_BIT_VALUE] = { .type = NLA_FLAG }, @@ -329,10 +327,10 @@ static const struct nla_policy bit_policy[ETHTOOL_A_BITSET_BIT_MAX + 1] = { */ int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact) { - struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1]; + struct nlattr *tb[ARRAY_SIZE(bitset_policy)]; int ret; - ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, bitset, + ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, bitset, bitset_policy, NULL); if (ret < 0) return ret; @@ -381,10 +379,10 @@ static int ethnl_parse_bit(unsigned int *index, bool *val, unsigned int nbits, ethnl_string_array_t names, struct netlink_ext_ack *extack) { - struct nlattr *tb[ETHTOOL_A_BITSET_BIT_MAX + 1]; + struct nlattr *tb[ARRAY_SIZE(bit_policy)]; int ret, idx; - ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_BIT_MAX, bit_attr, + ret = nla_parse_nested(tb, ARRAY_SIZE(bit_policy) - 1, bit_attr, bit_policy, extack); if (ret < 0) return ret; @@ -555,15 +553,15 @@ int ethnl_update_bitset32(u32 *bitmap, unsigned int nbits, const struct nlattr *attr, ethnl_string_array_t names, struct netlink_ext_ack *extack, bool *mod) { - struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1]; + struct nlattr *tb[ARRAY_SIZE(bitset_policy)]; unsigned int change_bits; bool no_mask; int ret; if (!attr) return 0; - ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, attr, bitset_policy, - extack); + ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, attr, + bitset_policy, extack); if (ret < 0) return ret; @@ -608,7 +606,7 @@ int ethnl_parse_bitset(unsigned long *val, unsigned long *mask, ethnl_string_array_t names, struct netlink_ext_ack *extack) { - struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1]; + struct nlattr *tb[ARRAY_SIZE(bitset_policy)]; const struct nlattr *bit_attr; bool no_mask; int rem; @@ -616,8 +614,8 @@ int ethnl_parse_bitset(unsigned long *val, unsigned long *mask, if (!attr) return 0; - ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, attr, bitset_policy, - extack); + ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, attr, + bitset_policy, extack); if (ret < 0) return ret; no_mask = tb[ETHTOOL_A_BITSET_NOMASK]; diff --git a/net/ethtool/cabletest.c b/net/ethtool/cabletest.c index 888f6e101f34..63560bbb7d1f 100644 --- a/net/ethtool/cabletest.c +++ b/net/ethtool/cabletest.c @@ -11,10 +11,9 @@ */ #define MAX_CABLE_LENGTH_CM (150 * 100) -static const struct nla_policy -cable_test_act_policy[ETHTOOL_A_CABLE_TEST_MAX + 1] = { - [ETHTOOL_A_CABLE_TEST_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_CABLE_TEST_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_cable_test_act_policy[] = { + [ETHTOOL_A_CABLE_TEST_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int ethnl_cable_test_started(struct phy_device *phydev, u8 cmd) @@ -56,18 +55,12 @@ out: int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_CABLE_TEST_MAX + 1]; struct ethnl_req_info req_info = {}; const struct ethtool_phy_ops *ops; + struct nlattr **tb = info->attrs; struct net_device *dev; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, - ETHTOOL_A_CABLE_TEST_MAX, - cable_test_act_policy, info->extack); - if (ret < 0) - return ret; - ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_CABLE_TEST_HEADER], genl_info_net(info), info->extack, @@ -218,18 +211,16 @@ struct cable_test_tdr_req_info { struct ethnl_req_info base; }; -static const struct nla_policy -cable_test_tdr_act_cfg_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX + 1] = { +static const struct nla_policy cable_test_tdr_act_cfg_policy[] = { [ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST] = { .type = NLA_U32 }, [ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST] = { .type = NLA_U32 }, [ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP] = { .type = NLA_U32 }, [ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR] = { .type = NLA_U8 }, }; -static const struct nla_policy -cable_test_tdr_act_policy[ETHTOOL_A_CABLE_TEST_TDR_MAX + 1] = { - [ETHTOOL_A_CABLE_TEST_TDR_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_CABLE_TEST_TDR_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_cable_test_tdr_act_policy[] = { + [ETHTOOL_A_CABLE_TEST_TDR_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_CABLE_TEST_TDR_CFG] = { .type = NLA_NESTED }, }; @@ -238,7 +229,7 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest, struct genl_info *info, struct phy_tdr_config *cfg) { - struct nlattr *tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX + 1]; + struct nlattr *tb[ARRAY_SIZE(cable_test_tdr_act_cfg_policy)]; int ret; cfg->first = 100; @@ -249,8 +240,10 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest, if (!nest) return 0; - ret = nla_parse_nested(tb, ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX, nest, - cable_test_tdr_act_cfg_policy, info->extack); + ret = nla_parse_nested(tb, + ARRAY_SIZE(cable_test_tdr_act_cfg_policy) - 1, + nest, cable_test_tdr_act_cfg_policy, + info->extack); if (ret < 0) return ret; @@ -313,19 +306,13 @@ static int ethnl_act_cable_test_tdr_cfg(const struct nlattr *nest, int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_CABLE_TEST_TDR_MAX + 1]; struct ethnl_req_info req_info = {}; const struct ethtool_phy_ops *ops; + struct nlattr **tb = info->attrs; struct phy_tdr_config cfg; struct net_device *dev; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, - ETHTOOL_A_CABLE_TEST_TDR_MAX, - cable_test_tdr_act_policy, info->extack); - if (ret < 0) - return ret; - ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_CABLE_TEST_TDR_HEADER], genl_info_net(info), info->extack, diff --git a/net/ethtool/channels.c b/net/ethtool/channels.c index 9ef54cdcf662..5635604cb9ba 100644 --- a/net/ethtool/channels.c +++ b/net/ethtool/channels.c @@ -17,18 +17,9 @@ struct channels_reply_data { #define CHANNELS_REPDATA(__reply_base) \ container_of(__reply_base, struct channels_reply_data, base) -static const struct nla_policy -channels_get_policy[ETHTOOL_A_CHANNELS_MAX + 1] = { - [ETHTOOL_A_CHANNELS_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_CHANNELS_RX_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_TX_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_OTHER_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_COMBINED_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_RX_COUNT] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_TX_COUNT] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_COMBINED_COUNT] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_channels_get_policy[] = { + [ETHTOOL_A_CHANNELS_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int channels_prepare_data(const struct ethnl_req_info *req_base, @@ -99,10 +90,8 @@ const struct ethnl_request_ops ethnl_channels_request_ops = { .request_cmd = ETHTOOL_MSG_CHANNELS_GET, .reply_cmd = ETHTOOL_MSG_CHANNELS_GET_REPLY, .hdr_attr = ETHTOOL_A_CHANNELS_HEADER, - .max_attr = ETHTOOL_A_CHANNELS_MAX, .req_info_size = sizeof(struct channels_req_info), .reply_data_size = sizeof(struct channels_reply_data), - .request_policy = channels_get_policy, .prepare_data = channels_prepare_data, .reply_size = channels_reply_size, @@ -111,14 +100,9 @@ const struct ethnl_request_ops ethnl_channels_request_ops = { /* CHANNELS_SET */ -static const struct nla_policy -channels_set_policy[ETHTOOL_A_CHANNELS_MAX + 1] = { - [ETHTOOL_A_CHANNELS_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_CHANNELS_RX_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_TX_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_OTHER_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_CHANNELS_COMBINED_MAX] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_channels_set_policy[] = { + [ETHTOOL_A_CHANNELS_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_CHANNELS_RX_COUNT] = { .type = NLA_U32 }, [ETHTOOL_A_CHANNELS_TX_COUNT] = { .type = NLA_U32 }, [ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .type = NLA_U32 }, @@ -127,22 +111,17 @@ channels_set_policy[ETHTOOL_A_CHANNELS_MAX + 1] = { int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_CHANNELS_MAX + 1]; unsigned int from_channel, old_total, i; bool mod = false, mod_combined = false; struct ethtool_channels channels = {}; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; const struct nlattr *err_attr; const struct ethtool_ops *ops; struct net_device *dev; u32 max_rx_in_use = 0; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, - ETHTOOL_A_CHANNELS_MAX, channels_set_policy, - info->extack); - if (ret < 0) - return ret; ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_CHANNELS_HEADER], genl_info_net(info), info->extack, @@ -223,7 +202,7 @@ int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info) from_channel = channels.combined_count + min(channels.rx_count, channels.tx_count); for (i = from_channel; i < old_total; i++) - if (xdp_get_umem_from_qid(dev, i)) { + if (xsk_get_pool_from_qid(dev, i)) { GENL_SET_ERR_MSG(info, "requested channel counts are too low for existing zerocopy AF_XDP sockets"); return -EINVAL; } diff --git a/net/ethtool/coalesce.c b/net/ethtool/coalesce.c index 6afd99042d67..1d6bc132aa4d 100644 --- a/net/ethtool/coalesce.c +++ b/net/ethtool/coalesce.c @@ -51,32 +51,9 @@ __CHECK_SUPPORTED_OFFSET(COALESCE_TX_USECS_HIGH); __CHECK_SUPPORTED_OFFSET(COALESCE_TX_MAX_FRAMES_HIGH); __CHECK_SUPPORTED_OFFSET(COALESCE_RATE_SAMPLE_INTERVAL); -static const struct nla_policy -coalesce_get_policy[ETHTOOL_A_COALESCE_MAX + 1] = { - [ETHTOOL_A_COALESCE_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_COALESCE_RX_USECS] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_RX_MAX_FRAMES] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_RX_USECS_IRQ] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_TX_USECS] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_TX_MAX_FRAMES] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_TX_USECS_IRQ] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_STATS_BLOCK_USECS] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_PKT_RATE_LOW] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_RX_USECS_LOW] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_TX_USECS_LOW] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_PKT_RATE_HIGH] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_RX_USECS_HIGH] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_TX_USECS_HIGH] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_coalesce_get_policy[] = { + [ETHTOOL_A_COALESCE_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int coalesce_prepare_data(const struct ethnl_req_info *req_base, @@ -203,10 +180,8 @@ const struct ethnl_request_ops ethnl_coalesce_request_ops = { .request_cmd = ETHTOOL_MSG_COALESCE_GET, .reply_cmd = ETHTOOL_MSG_COALESCE_GET_REPLY, .hdr_attr = ETHTOOL_A_COALESCE_HEADER, - .max_attr = ETHTOOL_A_COALESCE_MAX, .req_info_size = sizeof(struct coalesce_req_info), .reply_data_size = sizeof(struct coalesce_reply_data), - .request_policy = coalesce_get_policy, .prepare_data = coalesce_prepare_data, .reply_size = coalesce_reply_size, @@ -215,10 +190,9 @@ const struct ethnl_request_ops ethnl_coalesce_request_ops = { /* COALESCE_SET */ -static const struct nla_policy -coalesce_set_policy[ETHTOOL_A_COALESCE_MAX + 1] = { - [ETHTOOL_A_COALESCE_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_COALESCE_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_coalesce_set_policy[] = { + [ETHTOOL_A_COALESCE_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_COALESCE_RX_USECS] = { .type = NLA_U32 }, [ETHTOOL_A_COALESCE_RX_MAX_FRAMES] = { .type = NLA_U32 }, [ETHTOOL_A_COALESCE_RX_USECS_IRQ] = { .type = NLA_U32 }, @@ -245,9 +219,9 @@ coalesce_set_policy[ETHTOOL_A_COALESCE_MAX + 1] = { int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_COALESCE_MAX + 1]; struct ethtool_coalesce coalesce = {}; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; const struct ethtool_ops *ops; struct net_device *dev; u32 supported_params; @@ -255,11 +229,6 @@ int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info) int ret; u16 a; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, - ETHTOOL_A_COALESCE_MAX, coalesce_set_policy, - info->extack); - if (ret < 0) - return ret; ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_COALESCE_HEADER], genl_info_net(info), info->extack, diff --git a/net/ethtool/common.c b/net/ethtool/common.c index ed19573fccd7..24036e3055a1 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -192,6 +192,8 @@ const char link_mode_names[][ETH_GSTRING_LEN] = { __DEFINE_LINK_MODE_NAME(400000, LR4_ER4_FR4, Full), __DEFINE_LINK_MODE_NAME(400000, DR4, Full), __DEFINE_LINK_MODE_NAME(400000, CR4, Full), + __DEFINE_LINK_MODE_NAME(100, FX, Half), + __DEFINE_LINK_MODE_NAME(100, FX, Full), }; static_assert(ARRAY_SIZE(link_mode_names) == __ETHTOOL_LINK_MODE_MASK_NBITS); diff --git a/net/ethtool/debug.c b/net/ethtool/debug.c index 1bd026a29f3f..f99912d7957e 100644 --- a/net/ethtool/debug.c +++ b/net/ethtool/debug.c @@ -16,11 +16,9 @@ struct debug_reply_data { #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 }, +const struct nla_policy ethnl_debug_get_policy[] = { + [ETHTOOL_A_DEBUG_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int debug_prepare_data(const struct ethnl_req_info *req_base, @@ -69,10 +67,8 @@ 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, @@ -81,27 +77,21 @@ const struct ethnl_request_ops ethnl_debug_request_ops = { /* DEBUG_SET */ -static const struct nla_policy -debug_set_policy[ETHTOOL_A_DEBUG_MAX + 1] = { - [ETHTOOL_A_DEBUG_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_DEBUG_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_debug_set_policy[] = { + [ETHTOOL_A_DEBUG_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_DEBUG_MSGMASK] = { .type = NLA_NESTED }, }; int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_DEBUG_MAX + 1]; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; struct net_device *dev; bool mod = false; u32 msg_mask; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, - ETHTOOL_A_DEBUG_MAX, debug_set_policy, - info->extack); - if (ret < 0) - return ret; ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_DEBUG_HEADER], genl_info_net(info), info->extack, diff --git a/net/ethtool/eee.c b/net/ethtool/eee.c index 94aa19cff22f..901b7de941ab 100644 --- a/net/ethtool/eee.c +++ b/net/ethtool/eee.c @@ -19,16 +19,9 @@ struct eee_reply_data { #define EEE_REPDATA(__reply_base) \ container_of(__reply_base, struct eee_reply_data, base) -static const struct nla_policy -eee_get_policy[ETHTOOL_A_EEE_MAX + 1] = { - [ETHTOOL_A_EEE_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_EEE_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_EEE_MODES_OURS] = { .type = NLA_REJECT }, - [ETHTOOL_A_EEE_MODES_PEER] = { .type = NLA_REJECT }, - [ETHTOOL_A_EEE_ACTIVE] = { .type = NLA_REJECT }, - [ETHTOOL_A_EEE_ENABLED] = { .type = NLA_REJECT }, - [ETHTOOL_A_EEE_TX_LPI_ENABLED] = { .type = NLA_REJECT }, - [ETHTOOL_A_EEE_TX_LPI_TIMER] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_eee_get_policy[] = { + [ETHTOOL_A_EEE_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int eee_prepare_data(const struct ethnl_req_info *req_base, @@ -119,10 +112,8 @@ const struct ethnl_request_ops ethnl_eee_request_ops = { .request_cmd = ETHTOOL_MSG_EEE_GET, .reply_cmd = ETHTOOL_MSG_EEE_GET_REPLY, .hdr_attr = ETHTOOL_A_EEE_HEADER, - .max_attr = ETHTOOL_A_EEE_MAX, .req_info_size = sizeof(struct eee_req_info), .reply_data_size = sizeof(struct eee_reply_data), - .request_policy = eee_get_policy, .prepare_data = eee_prepare_data, .reply_size = eee_reply_size, @@ -131,13 +122,10 @@ const struct ethnl_request_ops ethnl_eee_request_ops = { /* EEE_SET */ -static const struct nla_policy -eee_set_policy[ETHTOOL_A_EEE_MAX + 1] = { - [ETHTOOL_A_EEE_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_EEE_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_eee_set_policy[] = { + [ETHTOOL_A_EEE_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_EEE_MODES_OURS] = { .type = NLA_NESTED }, - [ETHTOOL_A_EEE_MODES_PEER] = { .type = NLA_REJECT }, - [ETHTOOL_A_EEE_ACTIVE] = { .type = NLA_REJECT }, [ETHTOOL_A_EEE_ENABLED] = { .type = NLA_U8 }, [ETHTOOL_A_EEE_TX_LPI_ENABLED] = { .type = NLA_U8 }, [ETHTOOL_A_EEE_TX_LPI_TIMER] = { .type = NLA_U32 }, @@ -145,18 +133,14 @@ eee_set_policy[ETHTOOL_A_EEE_MAX + 1] = { int ethnl_set_eee(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_EEE_MAX + 1]; - struct ethtool_eee eee = {}; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; const struct ethtool_ops *ops; + struct ethtool_eee eee = {}; struct net_device *dev; bool mod = false; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_EEE_MAX, - eee_set_policy, info->extack); - if (ret < 0) - return ret; ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_EEE_HEADER], genl_info_net(info), info->extack, diff --git a/net/ethtool/features.c b/net/ethtool/features.c index 495635f152ba..8ee4cdbd6b82 100644 --- a/net/ethtool/features.c +++ b/net/ethtool/features.c @@ -20,14 +20,9 @@ struct features_reply_data { #define FEATURES_REPDATA(__reply_base) \ container_of(__reply_base, struct features_reply_data, base) -static const struct nla_policy -features_get_policy[ETHTOOL_A_FEATURES_MAX + 1] = { - [ETHTOOL_A_FEATURES_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_FEATURES_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_FEATURES_HW] = { .type = NLA_REJECT }, - [ETHTOOL_A_FEATURES_WANTED] = { .type = NLA_REJECT }, - [ETHTOOL_A_FEATURES_ACTIVE] = { .type = NLA_REJECT }, - [ETHTOOL_A_FEATURES_NOCHANGE] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_features_get_policy[] = { + [ETHTOOL_A_FEATURES_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static void ethnl_features_to_bitmap32(u32 *dest, netdev_features_t src) @@ -120,10 +115,8 @@ const struct ethnl_request_ops ethnl_features_request_ops = { .request_cmd = ETHTOOL_MSG_FEATURES_GET, .reply_cmd = ETHTOOL_MSG_FEATURES_GET_REPLY, .hdr_attr = ETHTOOL_A_FEATURES_HEADER, - .max_attr = ETHTOOL_A_FEATURES_MAX, .req_info_size = sizeof(struct features_req_info), .reply_data_size = sizeof(struct features_reply_data), - .request_policy = features_get_policy, .prepare_data = features_prepare_data, .reply_size = features_reply_size, @@ -132,14 +125,10 @@ const struct ethnl_request_ops ethnl_features_request_ops = { /* FEATURES_SET */ -static const struct nla_policy -features_set_policy[ETHTOOL_A_FEATURES_MAX + 1] = { - [ETHTOOL_A_FEATURES_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_FEATURES_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_FEATURES_HW] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_features_set_policy[] = { + [ETHTOOL_A_FEATURES_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_FEATURES_WANTED] = { .type = NLA_NESTED }, - [ETHTOOL_A_FEATURES_ACTIVE] = { .type = NLA_REJECT }, - [ETHTOOL_A_FEATURES_NOCHANGE] = { .type = NLA_REJECT }, }; static void ethnl_features_to_bitmap(unsigned long *dest, netdev_features_t val) @@ -229,17 +218,12 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) DECLARE_BITMAP(new_wanted, NETDEV_FEATURE_COUNT); DECLARE_BITMAP(req_wanted, NETDEV_FEATURE_COUNT); DECLARE_BITMAP(req_mask, NETDEV_FEATURE_COUNT); - struct nlattr *tb[ETHTOOL_A_FEATURES_MAX + 1]; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; struct net_device *dev; bool mod; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, - ETHTOOL_A_FEATURES_MAX, features_set_policy, - info->extack); - if (ret < 0) - return ret; if (!tb[ETHTOOL_A_FEATURES_WANTED]) return -EINVAL; ret = ethnl_parse_header_dev_get(&req_info, diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 441794e0034f..ec2cd7aab5ad 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1706,7 +1706,7 @@ static noinline_for_stack int ethtool_set_channels(struct net_device *dev, min(channels.rx_count, channels.tx_count); to_channel = curr.combined_count + max(curr.rx_count, curr.tx_count); for (i = from_channel; i < to_channel; i++) - if (xdp_get_umem_from_qid(dev, i)) + if (xsk_get_pool_from_qid(dev, i)) return -EINVAL; ret = dev->ethtool_ops->set_channels(dev, &channels); @@ -1861,23 +1861,18 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) id.data ? (id.data * HZ) : MAX_SCHEDULE_TIMEOUT); } else { /* Driver expects to be called at twice the frequency in rc */ - int n = rc * 2, i, interval = HZ / n; + int n = rc * 2, interval = HZ / n; + u64 count = n * id.data, i = 0; - /* Count down seconds */ do { - /* Count down iterations per second */ - i = n; - do { - rtnl_lock(); - rc = ops->set_phys_id(dev, - (i & 1) ? ETHTOOL_ID_OFF : ETHTOOL_ID_ON); - rtnl_unlock(); - if (rc) - break; - schedule_timeout_interruptible(interval); - } while (!signal_pending(current) && --i != 0); - } while (!signal_pending(current) && - (id.data == 0 || --id.data != 0)); + rtnl_lock(); + rc = ops->set_phys_id(dev, + (i++ & 1) ? ETHTOOL_ID_OFF : ETHTOOL_ID_ON); + rtnl_unlock(); + if (rc) + break; + schedule_timeout_interruptible(interval); + } while (!signal_pending(current) && (!id.data || i < count)); } rtnl_lock(); @@ -2464,14 +2459,15 @@ static int ethtool_phy_tunable_valid(const struct ethtool_tunable *tuna) static int get_phy_tunable(struct net_device *dev, void __user *useraddr) { - int ret; - struct ethtool_tunable tuna; struct phy_device *phydev = dev->phydev; + struct ethtool_tunable tuna; + bool phy_drv_tunable; void *data; + int ret; - if (!(phydev && phydev->drv && phydev->drv->get_tunable)) + phy_drv_tunable = phydev && phydev->drv && phydev->drv->get_tunable; + if (!phy_drv_tunable && !dev->ethtool_ops->get_phy_tunable) return -EOPNOTSUPP; - if (copy_from_user(&tuna, useraddr, sizeof(tuna))) return -EFAULT; ret = ethtool_phy_tunable_valid(&tuna); @@ -2480,9 +2476,13 @@ static int get_phy_tunable(struct net_device *dev, void __user *useraddr) data = kmalloc(tuna.len, GFP_USER); if (!data) return -ENOMEM; - mutex_lock(&phydev->lock); - ret = phydev->drv->get_tunable(phydev, &tuna, data); - mutex_unlock(&phydev->lock); + if (phy_drv_tunable) { + mutex_lock(&phydev->lock); + ret = phydev->drv->get_tunable(phydev, &tuna, data); + mutex_unlock(&phydev->lock); + } else { + ret = dev->ethtool_ops->get_phy_tunable(dev, &tuna, data); + } if (ret) goto out; useraddr += sizeof(tuna); @@ -2498,12 +2498,14 @@ out: static int set_phy_tunable(struct net_device *dev, void __user *useraddr) { - int ret; - struct ethtool_tunable tuna; struct phy_device *phydev = dev->phydev; + struct ethtool_tunable tuna; + bool phy_drv_tunable; void *data; + int ret; - if (!(phydev && phydev->drv && phydev->drv->set_tunable)) + phy_drv_tunable = phydev && phydev->drv && phydev->drv->get_tunable; + if (!phy_drv_tunable && !dev->ethtool_ops->set_phy_tunable) return -EOPNOTSUPP; if (copy_from_user(&tuna, useraddr, sizeof(tuna))) return -EFAULT; @@ -2514,9 +2516,13 @@ static int set_phy_tunable(struct net_device *dev, void __user *useraddr) data = memdup_user(useraddr, tuna.len); if (IS_ERR(data)) return PTR_ERR(data); - mutex_lock(&phydev->lock); - ret = phydev->drv->set_tunable(phydev, &tuna, data); - mutex_unlock(&phydev->lock); + if (phy_drv_tunable) { + mutex_lock(&phydev->lock); + ret = phydev->drv->set_tunable(phydev, &tuna, data); + mutex_unlock(&phydev->lock); + } else { + ret = dev->ethtool_ops->set_phy_tunable(dev, &tuna, data); + } kfree(data); return ret; @@ -3025,13 +3031,14 @@ ethtool_rx_flow_rule_create(const struct ethtool_rx_flow_spec_input *input) case TCP_V4_FLOW: case TCP_V6_FLOW: match->key.basic.ip_proto = IPPROTO_TCP; + match->mask.basic.ip_proto = 0xff; break; case UDP_V4_FLOW: case UDP_V6_FLOW: match->key.basic.ip_proto = IPPROTO_UDP; + match->mask.basic.ip_proto = 0xff; break; } - match->mask.basic.ip_proto = 0xff; match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_BASIC); match->dissector.offset[FLOW_DISSECTOR_KEY_BASIC] = diff --git a/net/ethtool/linkinfo.c b/net/ethtool/linkinfo.c index 5eaf173eaaca..b91839870efc 100644 --- a/net/ethtool/linkinfo.c +++ b/net/ethtool/linkinfo.c @@ -16,15 +16,9 @@ struct linkinfo_reply_data { #define LINKINFO_REPDATA(__reply_base) \ container_of(__reply_base, struct linkinfo_reply_data, base) -static const struct nla_policy -linkinfo_get_policy[ETHTOOL_A_LINKINFO_MAX + 1] = { - [ETHTOOL_A_LINKINFO_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKINFO_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_LINKINFO_PORT] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKINFO_PHYADDR] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKINFO_TP_MDIX] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKINFO_TRANSCEIVER] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_linkinfo_get_policy[] = { + [ETHTOOL_A_LINKINFO_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int linkinfo_prepare_data(const struct ethnl_req_info *req_base, @@ -83,10 +77,8 @@ const struct ethnl_request_ops ethnl_linkinfo_request_ops = { .request_cmd = ETHTOOL_MSG_LINKINFO_GET, .reply_cmd = ETHTOOL_MSG_LINKINFO_GET_REPLY, .hdr_attr = ETHTOOL_A_LINKINFO_HEADER, - .max_attr = ETHTOOL_A_LINKINFO_MAX, .req_info_size = sizeof(struct linkinfo_req_info), .reply_data_size = sizeof(struct linkinfo_reply_data), - .request_policy = linkinfo_get_policy, .prepare_data = linkinfo_prepare_data, .reply_size = linkinfo_reply_size, @@ -95,32 +87,24 @@ const struct ethnl_request_ops ethnl_linkinfo_request_ops = { /* LINKINFO_SET */ -static const struct nla_policy -linkinfo_set_policy[ETHTOOL_A_LINKINFO_MAX + 1] = { - [ETHTOOL_A_LINKINFO_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKINFO_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_linkinfo_set_policy[] = { + [ETHTOOL_A_LINKINFO_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_LINKINFO_PORT] = { .type = NLA_U8 }, [ETHTOOL_A_LINKINFO_PHYADDR] = { .type = NLA_U8 }, - [ETHTOOL_A_LINKINFO_TP_MDIX] = { .type = NLA_REJECT }, [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] = { .type = NLA_U8 }, - [ETHTOOL_A_LINKINFO_TRANSCEIVER] = { .type = NLA_REJECT }, }; int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_LINKINFO_MAX + 1]; struct ethtool_link_ksettings ksettings = {}; struct ethtool_link_settings *lsettings; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; struct net_device *dev; bool mod = false; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, - ETHTOOL_A_LINKINFO_MAX, linkinfo_set_policy, - info->extack); - if (ret < 0) - return ret; ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_LINKINFO_HEADER], genl_info_net(info), info->extack, diff --git a/net/ethtool/linkmodes.c b/net/ethtool/linkmodes.c index 7044a2853886..c5bcb9abc8b9 100644 --- a/net/ethtool/linkmodes.c +++ b/net/ethtool/linkmodes.c @@ -18,17 +18,9 @@ struct linkmodes_reply_data { #define LINKMODES_REPDATA(__reply_base) \ container_of(__reply_base, struct linkmodes_reply_data, base) -static const struct nla_policy -linkmodes_get_policy[ETHTOOL_A_LINKMODES_MAX + 1] = { - [ETHTOOL_A_LINKMODES_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKMODES_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_LINKMODES_AUTONEG] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKMODES_OURS] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKMODES_PEER] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKMODES_SPEED] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKMODES_DUPLEX] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_linkmodes_get_policy[] = { + [ETHTOOL_A_LINKMODES_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int linkmodes_prepare_data(const struct ethnl_req_info *req_base, @@ -148,10 +140,8 @@ const struct ethnl_request_ops ethnl_linkmodes_request_ops = { .request_cmd = ETHTOOL_MSG_LINKMODES_GET, .reply_cmd = ETHTOOL_MSG_LINKMODES_GET_REPLY, .hdr_attr = ETHTOOL_A_LINKMODES_HEADER, - .max_attr = ETHTOOL_A_LINKMODES_MAX, .req_info_size = sizeof(struct linkmodes_req_info), .reply_data_size = sizeof(struct linkmodes_reply_data), - .request_policy = linkmodes_get_policy, .prepare_data = linkmodes_prepare_data, .reply_size = linkmodes_reply_size, @@ -272,19 +262,18 @@ static const struct link_mode_info link_mode_params[] = { __DEFINE_LINK_MODE_PARAMS(400000, LR4_ER4_FR4, Full), __DEFINE_LINK_MODE_PARAMS(400000, DR4, Full), __DEFINE_LINK_MODE_PARAMS(400000, CR4, Full), + __DEFINE_LINK_MODE_PARAMS(100, FX, Half), + __DEFINE_LINK_MODE_PARAMS(100, FX, Full), }; -static const struct nla_policy -linkmodes_set_policy[ETHTOOL_A_LINKMODES_MAX + 1] = { - [ETHTOOL_A_LINKMODES_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKMODES_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_linkmodes_set_policy[] = { + [ETHTOOL_A_LINKMODES_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_LINKMODES_AUTONEG] = { .type = NLA_U8 }, [ETHTOOL_A_LINKMODES_OURS] = { .type = NLA_NESTED }, - [ETHTOOL_A_LINKMODES_PEER] = { .type = NLA_REJECT }, [ETHTOOL_A_LINKMODES_SPEED] = { .type = NLA_U32 }, [ETHTOOL_A_LINKMODES_DUPLEX] = { .type = NLA_U8 }, [ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG] = { .type = NLA_U8 }, - [ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE] = { .type = NLA_REJECT }, }; /* Set advertised link modes to all supported modes matching requested speed @@ -390,18 +379,13 @@ static int ethnl_update_linkmodes(struct genl_info *info, struct nlattr **tb, int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_LINKMODES_MAX + 1]; struct ethtool_link_ksettings ksettings = {}; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; struct net_device *dev; bool mod = false; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, - ETHTOOL_A_LINKMODES_MAX, linkmodes_set_policy, - info->extack); - if (ret < 0) - return ret; ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_LINKMODES_HEADER], genl_info_net(info), info->extack, diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c index 4834091ec24c..fb676f349455 100644 --- a/net/ethtool/linkstate.c +++ b/net/ethtool/linkstate.c @@ -20,15 +20,9 @@ struct linkstate_reply_data { #define LINKSTATE_REPDATA(__reply_base) \ container_of(__reply_base, struct linkstate_reply_data, base) -static const struct nla_policy -linkstate_get_policy[ETHTOOL_A_LINKSTATE_MAX + 1] = { - [ETHTOOL_A_LINKSTATE_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKSTATE_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_LINKSTATE_LINK] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKSTATE_SQI] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKSTATE_SQI_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKSTATE_EXT_STATE] = { .type = NLA_REJECT }, - [ETHTOOL_A_LINKSTATE_EXT_SUBSTATE] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_linkstate_get_policy[] = { + [ETHTOOL_A_LINKSTATE_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int linkstate_get_sqi(struct net_device *dev) @@ -179,10 +173,8 @@ const struct ethnl_request_ops ethnl_linkstate_request_ops = { .request_cmd = ETHTOOL_MSG_LINKSTATE_GET, .reply_cmd = ETHTOOL_MSG_LINKSTATE_GET_REPLY, .hdr_attr = ETHTOOL_A_LINKSTATE_HEADER, - .max_attr = ETHTOOL_A_LINKSTATE_MAX, .req_info_size = sizeof(struct linkstate_req_info), .reply_data_size = sizeof(struct linkstate_reply_data), - .request_policy = linkstate_get_policy, .prepare_data = linkstate_prepare_data, .reply_size = linkstate_reply_size, diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 0c3f54baec4e..50d3c8896f91 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -9,12 +9,24 @@ static struct genl_family ethtool_genl_family; static bool ethnl_ok __read_mostly; static u32 ethnl_bcast_seq; -static const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_MAX + 1] = { - [ETHTOOL_A_HEADER_UNSPEC] = { .type = NLA_REJECT }, +#define ETHTOOL_FLAGS_BASIC (ETHTOOL_FLAG_COMPACT_BITSETS | \ + ETHTOOL_FLAG_OMIT_REPLY) +#define ETHTOOL_FLAGS_STATS (ETHTOOL_FLAGS_BASIC | ETHTOOL_FLAG_STATS) + +const struct nla_policy ethnl_header_policy[] = { [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 }, [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING, .len = ALTIFNAMSIZ - 1 }, - [ETHTOOL_A_HEADER_FLAGS] = { .type = NLA_U32 }, + [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, + ETHTOOL_FLAGS_BASIC), +}; + +const struct nla_policy ethnl_header_policy_stats[] = { + [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 }, + [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING, + .len = ALTIFNAMSIZ - 1 }, + [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, + ETHTOOL_FLAGS_STATS), }; /** @@ -37,7 +49,7 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, const struct nlattr *header, struct net *net, struct netlink_ext_ack *extack, bool require_dev) { - struct nlattr *tb[ETHTOOL_A_HEADER_MAX + 1]; + struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy)]; const struct nlattr *devname_attr; struct net_device *dev = NULL; u32 flags = 0; @@ -47,19 +59,15 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, NL_SET_ERR_MSG(extack, "request header missing"); return -EINVAL; } - ret = nla_parse_nested(tb, ETHTOOL_A_HEADER_MAX, header, - ethnl_header_policy, extack); + /* No validation here, command policy should have a nested policy set + * for the header, therefore validation should have already been done. + */ + ret = nla_parse_nested(tb, ARRAY_SIZE(ethnl_header_policy) - 1, header, + NULL, extack); if (ret < 0) return ret; - if (tb[ETHTOOL_A_HEADER_FLAGS]) { + if (tb[ETHTOOL_A_HEADER_FLAGS]) flags = nla_get_u32(tb[ETHTOOL_A_HEADER_FLAGS]); - if (flags & ~ETHTOOL_FLAG_ALL) { - NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_HEADER_FLAGS], - "unrecognized request flags"); - nl_set_extack_cookie_u32(extack, ETHTOOL_FLAG_ALL); - return -EOPNOTSUPP; - } - } devname_attr = tb[ETHTOOL_A_HEADER_DEV_NAME]; if (tb[ETHTOOL_A_HEADER_DEV_INDEX]) { @@ -247,7 +255,7 @@ static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) /** * ethnl_default_parse() - Parse request message * @req_info: pointer to structure to put data into - * @nlhdr: pointer to request message header + * @tb: parsed attributes * @net: request netns * @request_ops: struct request_ops for request type * @extack: netlink extack for error reporting @@ -259,37 +267,24 @@ static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) * Return: 0 on success or negative error code */ static int ethnl_default_parse(struct ethnl_req_info *req_info, - const struct nlmsghdr *nlhdr, struct net *net, + struct nlattr **tb, struct net *net, const struct ethnl_request_ops *request_ops, struct netlink_ext_ack *extack, bool require_dev) { - struct nlattr **tb; int ret; - tb = kmalloc_array(request_ops->max_attr + 1, sizeof(tb[0]), - GFP_KERNEL); - if (!tb) - return -ENOMEM; - - ret = nlmsg_parse(nlhdr, GENL_HDRLEN, tb, request_ops->max_attr, - request_ops->request_policy, extack); - if (ret < 0) - goto out; ret = ethnl_parse_header_dev_get(req_info, tb[request_ops->hdr_attr], net, extack, require_dev); if (ret < 0) - goto out; + return ret; if (request_ops->parse_request) { ret = request_ops->parse_request(req_info, tb, extack); if (ret < 0) - goto out; + return ret; } - ret = 0; -out: - kfree(tb); - return ret; + return 0; } /** @@ -334,8 +329,8 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info) return -ENOMEM; } - ret = ethnl_default_parse(req_info, info->nlhdr, genl_info_net(info), ops, - info->extack, !ops->allow_nodev_do); + ret = ethnl_default_parse(req_info, info->attrs, genl_info_net(info), + ops, info->extack, !ops->allow_nodev_do); if (ret < 0) goto err_dev; ethnl_init_reply_data(reply_data, ops, req_info->dev); @@ -480,6 +475,7 @@ out: /* generic ->start() handler for GET requests */ static int ethnl_default_start(struct netlink_callback *cb) { + const struct genl_dumpit_info *info = genl_dumpit_info(cb); struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb); struct ethnl_reply_data *reply_data; const struct ethnl_request_ops *ops; @@ -502,8 +498,8 @@ static int ethnl_default_start(struct netlink_callback *cb) goto free_req_info; } - ret = ethnl_default_parse(req_info, cb->nlh, sock_net(cb->skb->sk), ops, - cb->extack, false); + ret = ethnl_default_parse(req_info, info->attrs, sock_net(cb->skb->sk), + ops, cb->extack, false); if (req_info->dev) { /* We ignore device specification in dump requests but as the * same parser as for non-dump (doit) requests is used, it @@ -696,6 +692,8 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_strset_get_policy, + .maxattr = ARRAY_SIZE(ethnl_strset_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_LINKINFO_GET, @@ -703,11 +701,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_linkinfo_get_policy, + .maxattr = ARRAY_SIZE(ethnl_linkinfo_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_LINKINFO_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_linkinfo, + .policy = ethnl_linkinfo_set_policy, + .maxattr = ARRAY_SIZE(ethnl_linkinfo_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_LINKMODES_GET, @@ -715,11 +717,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_linkmodes_get_policy, + .maxattr = ARRAY_SIZE(ethnl_linkmodes_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_LINKMODES_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_linkmodes, + .policy = ethnl_linkmodes_set_policy, + .maxattr = ARRAY_SIZE(ethnl_linkmodes_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_LINKSTATE_GET, @@ -727,6 +733,8 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_linkstate_get_policy, + .maxattr = ARRAY_SIZE(ethnl_linkstate_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_DEBUG_GET, @@ -734,11 +742,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_debug_get_policy, + .maxattr = ARRAY_SIZE(ethnl_debug_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_DEBUG_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_debug, + .policy = ethnl_debug_set_policy, + .maxattr = ARRAY_SIZE(ethnl_debug_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_WOL_GET, @@ -747,11 +759,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_wol_get_policy, + .maxattr = ARRAY_SIZE(ethnl_wol_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_WOL_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_wol, + .policy = ethnl_wol_set_policy, + .maxattr = ARRAY_SIZE(ethnl_wol_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_FEATURES_GET, @@ -759,11 +775,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_features_get_policy, + .maxattr = ARRAY_SIZE(ethnl_features_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_FEATURES_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_features, + .policy = ethnl_features_set_policy, + .maxattr = ARRAY_SIZE(ethnl_features_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_PRIVFLAGS_GET, @@ -771,11 +791,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_privflags_get_policy, + .maxattr = ARRAY_SIZE(ethnl_privflags_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_PRIVFLAGS_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_privflags, + .policy = ethnl_privflags_set_policy, + .maxattr = ARRAY_SIZE(ethnl_privflags_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_RINGS_GET, @@ -783,11 +807,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_rings_get_policy, + .maxattr = ARRAY_SIZE(ethnl_rings_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_RINGS_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_rings, + .policy = ethnl_rings_set_policy, + .maxattr = ARRAY_SIZE(ethnl_rings_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_CHANNELS_GET, @@ -795,11 +823,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_channels_get_policy, + .maxattr = ARRAY_SIZE(ethnl_channels_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_CHANNELS_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_channels, + .policy = ethnl_channels_set_policy, + .maxattr = ARRAY_SIZE(ethnl_channels_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_COALESCE_GET, @@ -807,11 +839,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_coalesce_get_policy, + .maxattr = ARRAY_SIZE(ethnl_coalesce_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_COALESCE_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_coalesce, + .policy = ethnl_coalesce_set_policy, + .maxattr = ARRAY_SIZE(ethnl_coalesce_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_PAUSE_GET, @@ -819,11 +855,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_pause_get_policy, + .maxattr = ARRAY_SIZE(ethnl_pause_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_PAUSE_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_pause, + .policy = ethnl_pause_set_policy, + .maxattr = ARRAY_SIZE(ethnl_pause_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_EEE_GET, @@ -831,11 +871,15 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_eee_get_policy, + .maxattr = ARRAY_SIZE(ethnl_eee_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_EEE_SET, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_eee, + .policy = ethnl_eee_set_policy, + .maxattr = ARRAY_SIZE(ethnl_eee_set_policy) - 1, }, { .cmd = ETHTOOL_MSG_TSINFO_GET, @@ -843,22 +887,30 @@ static const struct genl_ops ethtool_genl_ops[] = { .start = ethnl_default_start, .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, + .policy = ethnl_tsinfo_get_policy, + .maxattr = ARRAY_SIZE(ethnl_tsinfo_get_policy) - 1, }, { .cmd = ETHTOOL_MSG_CABLE_TEST_ACT, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_act_cable_test, + .policy = ethnl_cable_test_act_policy, + .maxattr = ARRAY_SIZE(ethnl_cable_test_act_policy) - 1, }, { .cmd = ETHTOOL_MSG_CABLE_TEST_TDR_ACT, .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_act_cable_test_tdr, + .policy = ethnl_cable_test_tdr_act_policy, + .maxattr = ARRAY_SIZE(ethnl_cable_test_tdr_act_policy) - 1, }, { .cmd = ETHTOOL_MSG_TUNNEL_INFO_GET, .doit = ethnl_tunnel_info_doit, .start = ethnl_tunnel_info_start, .dumpit = ethnl_tunnel_info_dumpit, + .policy = ethnl_tunnel_info_get_policy, + .maxattr = ARRAY_SIZE(ethnl_tunnel_info_get_policy) - 1, }, }; diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index e2085005caac..d8efec516d86 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -266,10 +266,8 @@ static inline void ethnl_ops_complete(struct net_device *dev) * @request_cmd: command id for request (GET) * @reply_cmd: command id for reply (GET_REPLY) * @hdr_attr: attribute type for request header - * @max_attr: maximum (top level) attribute type * @req_info_size: size of request info * @reply_data_size: size of reply data - * @request_policy: netlink policy for message contents * @allow_nodev_do: allow non-dump request with no device identification * @parse_request: * Parse request except common header (struct ethnl_req_info). Common @@ -312,10 +310,8 @@ struct ethnl_request_ops { u8 request_cmd; u8 reply_cmd; u16 hdr_attr; - unsigned int max_attr; unsigned int req_info_size; unsigned int reply_data_size; - const struct nla_policy *request_policy; bool allow_nodev_do; int (*parse_request)(struct ethnl_req_info *req_info, @@ -349,6 +345,37 @@ extern const struct ethnl_request_ops ethnl_pause_request_ops; extern const struct ethnl_request_ops ethnl_eee_request_ops; extern const struct ethnl_request_ops ethnl_tsinfo_request_ops; +extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1]; +extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1]; +extern const struct nla_policy ethnl_strset_get_policy[ETHTOOL_A_STRSET_COUNTS_ONLY + 1]; +extern const struct nla_policy ethnl_linkinfo_get_policy[ETHTOOL_A_LINKINFO_HEADER + 1]; +extern const struct nla_policy ethnl_linkinfo_set_policy[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL + 1]; +extern const struct nla_policy ethnl_linkmodes_get_policy[ETHTOOL_A_LINKMODES_HEADER + 1]; +extern const struct nla_policy ethnl_linkmodes_set_policy[ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG + 1]; +extern const struct nla_policy ethnl_linkstate_get_policy[ETHTOOL_A_LINKSTATE_HEADER + 1]; +extern const struct nla_policy ethnl_debug_get_policy[ETHTOOL_A_DEBUG_HEADER + 1]; +extern const struct nla_policy ethnl_debug_set_policy[ETHTOOL_A_DEBUG_MSGMASK + 1]; +extern const struct nla_policy ethnl_wol_get_policy[ETHTOOL_A_WOL_HEADER + 1]; +extern const struct nla_policy ethnl_wol_set_policy[ETHTOOL_A_WOL_SOPASS + 1]; +extern const struct nla_policy ethnl_features_get_policy[ETHTOOL_A_FEATURES_HEADER + 1]; +extern const struct nla_policy ethnl_features_set_policy[ETHTOOL_A_FEATURES_WANTED + 1]; +extern const struct nla_policy ethnl_privflags_get_policy[ETHTOOL_A_PRIVFLAGS_HEADER + 1]; +extern const struct nla_policy ethnl_privflags_set_policy[ETHTOOL_A_PRIVFLAGS_FLAGS + 1]; +extern const struct nla_policy ethnl_rings_get_policy[ETHTOOL_A_RINGS_HEADER + 1]; +extern const struct nla_policy ethnl_rings_set_policy[ETHTOOL_A_RINGS_TX + 1]; +extern const struct nla_policy ethnl_channels_get_policy[ETHTOOL_A_CHANNELS_HEADER + 1]; +extern const struct nla_policy ethnl_channels_set_policy[ETHTOOL_A_CHANNELS_COMBINED_COUNT + 1]; +extern const struct nla_policy ethnl_coalesce_get_policy[ETHTOOL_A_COALESCE_HEADER + 1]; +extern const struct nla_policy ethnl_coalesce_set_policy[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL + 1]; +extern const struct nla_policy ethnl_pause_get_policy[ETHTOOL_A_PAUSE_HEADER + 1]; +extern const struct nla_policy ethnl_pause_set_policy[ETHTOOL_A_PAUSE_TX + 1]; +extern const struct nla_policy ethnl_eee_get_policy[ETHTOOL_A_EEE_HEADER + 1]; +extern const struct nla_policy ethnl_eee_set_policy[ETHTOOL_A_EEE_TX_LPI_TIMER + 1]; +extern const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_HEADER + 1]; +extern const struct nla_policy ethnl_cable_test_act_policy[ETHTOOL_A_CABLE_TEST_HEADER + 1]; +extern const struct nla_policy ethnl_cable_test_tdr_act_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG + 1]; +extern const struct nla_policy ethnl_tunnel_info_get_policy[ETHTOOL_A_TUNNEL_INFO_HEADER + 1]; + int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info); int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info); int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info); diff --git a/net/ethtool/pause.c b/net/ethtool/pause.c index 7aea35d1e8a5..09998dc5c185 100644 --- a/net/ethtool/pause.c +++ b/net/ethtool/pause.c @@ -10,20 +10,23 @@ struct pause_req_info { struct pause_reply_data { struct ethnl_reply_data base; struct ethtool_pauseparam pauseparam; + struct ethtool_pause_stats pausestat; }; #define PAUSE_REPDATA(__reply_base) \ container_of(__reply_base, struct pause_reply_data, base) -static const struct nla_policy -pause_get_policy[ETHTOOL_A_PAUSE_MAX + 1] = { - [ETHTOOL_A_PAUSE_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_PAUSE_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_PAUSE_AUTONEG] = { .type = NLA_REJECT }, - [ETHTOOL_A_PAUSE_RX] = { .type = NLA_REJECT }, - [ETHTOOL_A_PAUSE_TX] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_pause_get_policy[] = { + [ETHTOOL_A_PAUSE_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy_stats), }; +static void ethtool_stats_init(u64 *stats, unsigned int n) +{ + while (n--) + stats[n] = ETHTOOL_STAT_NOT_SET; +} + static int pause_prepare_data(const struct ethnl_req_info *req_base, struct ethnl_reply_data *reply_base, struct genl_info *info) @@ -34,10 +37,17 @@ static int pause_prepare_data(const struct ethnl_req_info *req_base, if (!dev->ethtool_ops->get_pauseparam) return -EOPNOTSUPP; + ret = ethnl_ops_begin(dev); if (ret < 0) return ret; dev->ethtool_ops->get_pauseparam(dev, &data->pauseparam); + if (req_base->flags & ETHTOOL_FLAG_STATS && + dev->ethtool_ops->get_pause_stats) { + ethtool_stats_init((u64 *)&data->pausestat, + sizeof(data->pausestat) / 8); + dev->ethtool_ops->get_pause_stats(dev, &data->pausestat); + } ethnl_ops_complete(dev); return 0; @@ -46,9 +56,50 @@ static int pause_prepare_data(const struct ethnl_req_info *req_base, static int pause_reply_size(const struct ethnl_req_info *req_base, const struct ethnl_reply_data *reply_base) { - return nla_total_size(sizeof(u8)) + /* _PAUSE_AUTONEG */ + int n = nla_total_size(sizeof(u8)) + /* _PAUSE_AUTONEG */ nla_total_size(sizeof(u8)) + /* _PAUSE_RX */ nla_total_size(sizeof(u8)); /* _PAUSE_TX */ + + if (req_base->flags & ETHTOOL_FLAG_STATS) + n += nla_total_size(0) + /* _PAUSE_STATS */ + nla_total_size_64bit(sizeof(u64)) * + (ETHTOOL_A_PAUSE_STAT_MAX - 2); + return n; +} + +static int ethtool_put_stat(struct sk_buff *skb, u64 val, u16 attrtype, + u16 padtype) +{ + if (val == ETHTOOL_STAT_NOT_SET) + return 0; + if (nla_put_u64_64bit(skb, attrtype, val, padtype)) + return -EMSGSIZE; + + return 0; +} + +static int pause_put_stats(struct sk_buff *skb, + const struct ethtool_pause_stats *pause_stats) +{ + const u16 pad = ETHTOOL_A_PAUSE_STAT_PAD; + struct nlattr *nest; + + nest = nla_nest_start(skb, ETHTOOL_A_PAUSE_STATS); + if (!nest) + return -EMSGSIZE; + + if (ethtool_put_stat(skb, pause_stats->tx_pause_frames, + ETHTOOL_A_PAUSE_STAT_TX_FRAMES, pad) || + ethtool_put_stat(skb, pause_stats->rx_pause_frames, + ETHTOOL_A_PAUSE_STAT_RX_FRAMES, pad)) + goto err_cancel; + + nla_nest_end(skb, nest); + return 0; + +err_cancel: + nla_nest_cancel(skb, nest); + return -EMSGSIZE; } static int pause_fill_reply(struct sk_buff *skb, @@ -63,6 +114,10 @@ static int pause_fill_reply(struct sk_buff *skb, nla_put_u8(skb, ETHTOOL_A_PAUSE_TX, !!pauseparam->tx_pause)) return -EMSGSIZE; + if (req_base->flags & ETHTOOL_FLAG_STATS && + pause_put_stats(skb, &data->pausestat)) + return -EMSGSIZE; + return 0; } @@ -70,10 +125,8 @@ const struct ethnl_request_ops ethnl_pause_request_ops = { .request_cmd = ETHTOOL_MSG_PAUSE_GET, .reply_cmd = ETHTOOL_MSG_PAUSE_GET_REPLY, .hdr_attr = ETHTOOL_A_PAUSE_HEADER, - .max_attr = ETHTOOL_A_PAUSE_MAX, .req_info_size = sizeof(struct pause_req_info), .reply_data_size = sizeof(struct pause_reply_data), - .request_policy = pause_get_policy, .prepare_data = pause_prepare_data, .reply_size = pause_reply_size, @@ -82,10 +135,9 @@ const struct ethnl_request_ops ethnl_pause_request_ops = { /* PAUSE_SET */ -static const struct nla_policy -pause_set_policy[ETHTOOL_A_PAUSE_MAX + 1] = { - [ETHTOOL_A_PAUSE_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_PAUSE_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_pause_set_policy[] = { + [ETHTOOL_A_PAUSE_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_PAUSE_AUTONEG] = { .type = NLA_U8 }, [ETHTOOL_A_PAUSE_RX] = { .type = NLA_U8 }, [ETHTOOL_A_PAUSE_TX] = { .type = NLA_U8 }, @@ -93,18 +145,14 @@ pause_set_policy[ETHTOOL_A_PAUSE_MAX + 1] = { int ethnl_set_pause(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_PAUSE_MAX + 1]; struct ethtool_pauseparam params = {}; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; const struct ethtool_ops *ops; struct net_device *dev; bool mod = false; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_PAUSE_MAX, - pause_set_policy, info->extack); - if (ret < 0) - return ret; ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_PAUSE_HEADER], genl_info_net(info), info->extack, diff --git a/net/ethtool/privflags.c b/net/ethtool/privflags.c index 77447dceb109..fc9f3be23a19 100644 --- a/net/ethtool/privflags.c +++ b/net/ethtool/privflags.c @@ -18,11 +18,9 @@ struct privflags_reply_data { #define PRIVFLAGS_REPDATA(__reply_base) \ container_of(__reply_base, struct privflags_reply_data, base) -static const struct nla_policy -privflags_get_policy[ETHTOOL_A_PRIVFLAGS_MAX + 1] = { - [ETHTOOL_A_PRIVFLAGS_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_PRIVFLAGS_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_PRIVFLAGS_FLAGS] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_privflags_get_policy[] = { + [ETHTOOL_A_PRIVFLAGS_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int ethnl_get_priv_flags_info(struct net_device *dev, @@ -124,10 +122,8 @@ const struct ethnl_request_ops ethnl_privflags_request_ops = { .request_cmd = ETHTOOL_MSG_PRIVFLAGS_GET, .reply_cmd = ETHTOOL_MSG_PRIVFLAGS_GET_REPLY, .hdr_attr = ETHTOOL_A_PRIVFLAGS_HEADER, - .max_attr = ETHTOOL_A_PRIVFLAGS_MAX, .req_info_size = sizeof(struct privflags_req_info), .reply_data_size = sizeof(struct privflags_reply_data), - .request_policy = privflags_get_policy, .prepare_data = privflags_prepare_data, .reply_size = privflags_reply_size, @@ -137,18 +133,17 @@ const struct ethnl_request_ops ethnl_privflags_request_ops = { /* PRIVFLAGS_SET */ -static const struct nla_policy -privflags_set_policy[ETHTOOL_A_PRIVFLAGS_MAX + 1] = { - [ETHTOOL_A_PRIVFLAGS_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_PRIVFLAGS_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_privflags_set_policy[] = { + [ETHTOOL_A_PRIVFLAGS_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_PRIVFLAGS_FLAGS] = { .type = NLA_NESTED }, }; int ethnl_set_privflags(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_PRIVFLAGS_MAX + 1]; const char (*names)[ETH_GSTRING_LEN] = NULL; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; const struct ethtool_ops *ops; struct net_device *dev; unsigned int nflags; @@ -157,11 +152,6 @@ int ethnl_set_privflags(struct sk_buff *skb, struct genl_info *info) u32 flags; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, - ETHTOOL_A_PRIVFLAGS_MAX, privflags_set_policy, - info->extack); - if (ret < 0) - return ret; if (!tb[ETHTOOL_A_PRIVFLAGS_FLAGS]) return -EINVAL; ret = ethnl_bitset_is_compact(tb[ETHTOOL_A_PRIVFLAGS_FLAGS], &compact); diff --git a/net/ethtool/rings.c b/net/ethtool/rings.c index 5422526f4eef..4e097812a967 100644 --- a/net/ethtool/rings.c +++ b/net/ethtool/rings.c @@ -15,18 +15,9 @@ struct rings_reply_data { #define RINGS_REPDATA(__reply_base) \ container_of(__reply_base, struct rings_reply_data, base) -static const struct nla_policy -rings_get_policy[ETHTOOL_A_RINGS_MAX + 1] = { - [ETHTOOL_A_RINGS_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_RINGS_RX_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_RX_MINI_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_RX_JUMBO_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_TX_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_RX] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_RX_MINI] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_RX_JUMBO] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_TX] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_rings_get_policy[] = { + [ETHTOOL_A_RINGS_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int rings_prepare_data(const struct ethnl_req_info *req_base, @@ -97,10 +88,8 @@ const struct ethnl_request_ops ethnl_rings_request_ops = { .request_cmd = ETHTOOL_MSG_RINGS_GET, .reply_cmd = ETHTOOL_MSG_RINGS_GET_REPLY, .hdr_attr = ETHTOOL_A_RINGS_HEADER, - .max_attr = ETHTOOL_A_RINGS_MAX, .req_info_size = sizeof(struct rings_req_info), .reply_data_size = sizeof(struct rings_reply_data), - .request_policy = rings_get_policy, .prepare_data = rings_prepare_data, .reply_size = rings_reply_size, @@ -109,14 +98,9 @@ const struct ethnl_request_ops ethnl_rings_request_ops = { /* RINGS_SET */ -static const struct nla_policy -rings_set_policy[ETHTOOL_A_RINGS_MAX + 1] = { - [ETHTOOL_A_RINGS_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_RINGS_RX_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_RX_MINI_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_RX_JUMBO_MAX] = { .type = NLA_REJECT }, - [ETHTOOL_A_RINGS_TX_MAX] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_rings_set_policy[] = { + [ETHTOOL_A_RINGS_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_RINGS_RX] = { .type = NLA_U32 }, [ETHTOOL_A_RINGS_RX_MINI] = { .type = NLA_U32 }, [ETHTOOL_A_RINGS_RX_JUMBO] = { .type = NLA_U32 }, @@ -125,20 +109,15 @@ rings_set_policy[ETHTOOL_A_RINGS_MAX + 1] = { int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *tb[ETHTOOL_A_RINGS_MAX + 1]; struct ethtool_ringparam ringparam = {}; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; const struct nlattr *err_attr; const struct ethtool_ops *ops; struct net_device *dev; bool mod = false; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, - ETHTOOL_A_RINGS_MAX, rings_set_policy, - info->extack); - if (ret < 0) - return ret; ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_RINGS_HEADER], genl_info_net(info), info->extack, diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c index 82707b662fe4..0baad0ce1832 100644 --- a/net/ethtool/strset.c +++ b/net/ethtool/strset.c @@ -99,18 +99,15 @@ struct strset_reply_data { #define STRSET_REPDATA(__reply_base) \ container_of(__reply_base, struct strset_reply_data, base) -static const struct nla_policy strset_get_policy[ETHTOOL_A_STRSET_MAX + 1] = { - [ETHTOOL_A_STRSET_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_STRSET_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_strset_get_policy[] = { + [ETHTOOL_A_STRSET_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_STRSET_STRINGSETS] = { .type = NLA_NESTED }, + [ETHTOOL_A_STRSET_COUNTS_ONLY] = { .type = NLA_FLAG }, }; -static const struct nla_policy -get_stringset_policy[ETHTOOL_A_STRINGSET_MAX + 1] = { - [ETHTOOL_A_STRINGSET_UNSPEC] = { .type = NLA_REJECT }, +static const struct nla_policy get_stringset_policy[] = { [ETHTOOL_A_STRINGSET_ID] = { .type = NLA_U32 }, - [ETHTOOL_A_STRINGSET_COUNT] = { .type = NLA_REJECT }, - [ETHTOOL_A_STRINGSET_STRINGS] = { .type = NLA_REJECT }, }; /** @@ -138,10 +135,10 @@ static bool strset_include(const struct strset_req_info *info, static int strset_get_id(const struct nlattr *nest, u32 *val, struct netlink_ext_ack *extack) { - struct nlattr *tb[ETHTOOL_A_STRINGSET_MAX + 1]; + struct nlattr *tb[ARRAY_SIZE(get_stringset_policy)]; int ret; - ret = nla_parse_nested(tb, ETHTOOL_A_STRINGSET_MAX, nest, + ret = nla_parse_nested(tb, ARRAY_SIZE(get_stringset_policy) - 1, nest, get_stringset_policy, extack); if (ret < 0) return ret; @@ -152,9 +149,7 @@ static int strset_get_id(const struct nlattr *nest, u32 *val, return 0; } -static const struct nla_policy -strset_stringsets_policy[ETHTOOL_A_STRINGSETS_MAX + 1] = { - [ETHTOOL_A_STRINGSETS_UNSPEC] = { .type = NLA_REJECT }, +static const struct nla_policy strset_stringsets_policy[] = { [ETHTOOL_A_STRINGSETS_STRINGSET] = { .type = NLA_NESTED }, }; @@ -169,7 +164,8 @@ static int strset_parse_request(struct ethnl_req_info *req_base, if (!nest) return 0; - ret = nla_validate_nested(nest, ETHTOOL_A_STRINGSETS_MAX, + ret = nla_validate_nested(nest, + ARRAY_SIZE(strset_stringsets_policy) - 1, strset_stringsets_policy, extack); if (ret < 0) return ret; @@ -445,10 +441,8 @@ const struct ethnl_request_ops ethnl_strset_request_ops = { .request_cmd = ETHTOOL_MSG_STRSET_GET, .reply_cmd = ETHTOOL_MSG_STRSET_GET_REPLY, .hdr_attr = ETHTOOL_A_STRSET_HEADER, - .max_attr = ETHTOOL_A_STRSET_MAX, .req_info_size = sizeof(struct strset_req_info), .reply_data_size = sizeof(struct strset_reply_data), - .request_policy = strset_get_policy, .allow_nodev_do = true, .parse_request = strset_parse_request, diff --git a/net/ethtool/tsinfo.c b/net/ethtool/tsinfo.c index 7cb5b512b77c..63b5814bd460 100644 --- a/net/ethtool/tsinfo.c +++ b/net/ethtool/tsinfo.c @@ -18,14 +18,9 @@ struct tsinfo_reply_data { #define TSINFO_REPDATA(__reply_base) \ container_of(__reply_base, struct tsinfo_reply_data, base) -static const struct nla_policy -tsinfo_get_policy[ETHTOOL_A_TSINFO_MAX + 1] = { - [ETHTOOL_A_TSINFO_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_TSINFO_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_TSINFO_TIMESTAMPING] = { .type = NLA_REJECT }, - [ETHTOOL_A_TSINFO_TX_TYPES] = { .type = NLA_REJECT }, - [ETHTOOL_A_TSINFO_RX_FILTERS] = { .type = NLA_REJECT }, - [ETHTOOL_A_TSINFO_PHC_INDEX] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_tsinfo_get_policy[] = { + [ETHTOOL_A_TSINFO_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int tsinfo_prepare_data(const struct ethnl_req_info *req_base, @@ -132,10 +127,8 @@ const struct ethnl_request_ops ethnl_tsinfo_request_ops = { .request_cmd = ETHTOOL_MSG_TSINFO_GET, .reply_cmd = ETHTOOL_MSG_TSINFO_GET_REPLY, .hdr_attr = ETHTOOL_A_TSINFO_HEADER, - .max_attr = ETHTOOL_A_TSINFO_MAX, .req_info_size = sizeof(struct tsinfo_req_info), .reply_data_size = sizeof(struct tsinfo_reply_data), - .request_policy = tsinfo_get_policy, .prepare_data = tsinfo_prepare_data, .reply_size = tsinfo_reply_size, diff --git a/net/ethtool/tunnels.c b/net/ethtool/tunnels.c index d93bf2da0f34..e7f2ee0d2471 100644 --- a/net/ethtool/tunnels.c +++ b/net/ethtool/tunnels.c @@ -8,10 +8,9 @@ #include "common.h" #include "netlink.h" -static const struct nla_policy -ethtool_tunnel_info_policy[ETHTOOL_A_TUNNEL_INFO_MAX + 1] = { - [ETHTOOL_A_TUNNEL_INFO_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_TUNNEL_INFO_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_tunnel_info_get_policy[] = { + [ETHTOOL_A_TUNNEL_INFO_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static_assert(ETHTOOL_UDP_TUNNEL_TYPE_VXLAN == ilog2(UDP_TUNNEL_TYPE_VXLAN)); @@ -161,35 +160,19 @@ err_cancel_ports: return -EMSGSIZE; } -static int -ethnl_tunnel_info_req_parse(struct ethnl_req_info *req_info, - const struct nlmsghdr *nlhdr, struct net *net, - struct netlink_ext_ack *extack, bool require_dev) -{ - struct nlattr *tb[ETHTOOL_A_TUNNEL_INFO_MAX + 1]; - int ret; - - ret = nlmsg_parse(nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_TUNNEL_INFO_MAX, - ethtool_tunnel_info_policy, extack); - if (ret < 0) - return ret; - - return ethnl_parse_header_dev_get(req_info, - tb[ETHTOOL_A_TUNNEL_INFO_HEADER], - net, extack, require_dev); -} - int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info) { struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; struct sk_buff *rskb; void *reply_payload; int reply_len; int ret; - ret = ethnl_tunnel_info_req_parse(&req_info, info->nlhdr, - genl_info_net(info), info->extack, - true); + ret = ethnl_parse_header_dev_get(&req_info, + tb[ETHTOOL_A_TUNNEL_INFO_HEADER], + genl_info_net(info), info->extack, + true); if (ret < 0) return ret; @@ -233,16 +216,19 @@ struct ethnl_tunnel_info_dump_ctx { int ethnl_tunnel_info_start(struct netlink_callback *cb) { + const struct genl_dumpit_info *info = genl_dumpit_info(cb); struct ethnl_tunnel_info_dump_ctx *ctx = (void *)cb->ctx; + struct nlattr **tb = info->attrs; int ret; BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); memset(ctx, 0, sizeof(*ctx)); - ret = ethnl_tunnel_info_req_parse(&ctx->req_info, cb->nlh, - sock_net(cb->skb->sk), cb->extack, - false); + ret = ethnl_parse_header_dev_get(&ctx->req_info, + tb[ETHTOOL_A_TUNNEL_INFO_HEADER], + sock_net(cb->skb->sk), cb->extack, + false); if (ctx->req_info.dev) { dev_put(ctx->req_info.dev); ctx->req_info.dev = NULL; diff --git a/net/ethtool/wol.c b/net/ethtool/wol.c index 1798421e9f1c..ada7df2331d2 100644 --- a/net/ethtool/wol.c +++ b/net/ethtool/wol.c @@ -17,12 +17,9 @@ struct wol_reply_data { #define WOL_REPDATA(__reply_base) \ container_of(__reply_base, struct wol_reply_data, base) -static const struct nla_policy -wol_get_policy[ETHTOOL_A_WOL_MAX + 1] = { - [ETHTOOL_A_WOL_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_WOL_HEADER] = { .type = NLA_NESTED }, - [ETHTOOL_A_WOL_MODES] = { .type = NLA_REJECT }, - [ETHTOOL_A_WOL_SOPASS] = { .type = NLA_REJECT }, +const struct nla_policy ethnl_wol_get_policy[] = { + [ETHTOOL_A_WOL_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), }; static int wol_prepare_data(const struct ethnl_req_info *req_base, @@ -89,10 +86,8 @@ const struct ethnl_request_ops ethnl_wol_request_ops = { .request_cmd = ETHTOOL_MSG_WOL_GET, .reply_cmd = ETHTOOL_MSG_WOL_GET_REPLY, .hdr_attr = ETHTOOL_A_WOL_HEADER, - .max_attr = ETHTOOL_A_WOL_MAX, .req_info_size = sizeof(struct wol_req_info), .reply_data_size = sizeof(struct wol_reply_data), - .request_policy = wol_get_policy, .prepare_data = wol_prepare_data, .reply_size = wol_reply_size, @@ -101,10 +96,9 @@ const struct ethnl_request_ops ethnl_wol_request_ops = { /* WOL_SET */ -static const struct nla_policy -wol_set_policy[ETHTOOL_A_WOL_MAX + 1] = { - [ETHTOOL_A_WOL_UNSPEC] = { .type = NLA_REJECT }, - [ETHTOOL_A_WOL_HEADER] = { .type = NLA_NESTED }, +const struct nla_policy ethnl_wol_set_policy[] = { + [ETHTOOL_A_WOL_HEADER] = + NLA_POLICY_NESTED(ethnl_header_policy), [ETHTOOL_A_WOL_MODES] = { .type = NLA_NESTED }, [ETHTOOL_A_WOL_SOPASS] = { .type = NLA_BINARY, .len = SOPASS_MAX }, @@ -113,16 +107,12 @@ wol_set_policy[ETHTOOL_A_WOL_MAX + 1] = { int ethnl_set_wol(struct sk_buff *skb, struct genl_info *info) { struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; - struct nlattr *tb[ETHTOOL_A_WOL_MAX + 1]; struct ethnl_req_info req_info = {}; + struct nlattr **tb = info->attrs; struct net_device *dev; bool mod = false; int ret; - ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_WOL_MAX, - wol_set_policy, info->extack); - if (ret < 0) - return ret; ret = ethnl_parse_header_dev_get(&req_info, tb[ETHTOOL_A_WOL_HEADER], genl_info_net(info), info->extack, true); |