mirror of
https://github.com/torvalds/linux.git
synced 2025-08-15 14:11:42 +02:00
ethtool: rss: support removing contexts via Netlink
Implement removing additional RSS contexts via Netlink. Technically it'd be possible to shoehorn the delete operation into ethnl_request_ops-compatible handler. The code ends up longer than open coded version, and I think we'll need a custom way of sending notifications at some stage (if we allow tying the context lifetime to the netlink socket, in the future). Link: https://patch.msgid.link/20250717234343.2328602-8-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
a166ab7816
commit
fbe09277fa
8 changed files with 153 additions and 1 deletions
|
@ -2706,6 +2706,24 @@ operations:
|
|||
doc: |
|
||||
Notification for creation of an additional RSS context.
|
||||
notify: rss-create-act
|
||||
-
|
||||
name: rss-delete-act
|
||||
doc: Delete an RSS context.
|
||||
attribute-set: rss
|
||||
do:
|
||||
request:
|
||||
attributes:
|
||||
- header
|
||||
- context
|
||||
-
|
||||
name: rss-delete-ntf
|
||||
doc: |
|
||||
Notification for deletion of an additional RSS context.
|
||||
attribute-set: rss
|
||||
event:
|
||||
attributes:
|
||||
- header
|
||||
- context
|
||||
|
||||
mcast-groups:
|
||||
list:
|
||||
|
|
|
@ -241,6 +241,7 @@ Userspace to kernel:
|
|||
``ETHTOOL_MSG_TSCONFIG_SET`` set hw timestamping configuration
|
||||
``ETHTOOL_MSG_RSS_SET`` set RSS settings
|
||||
``ETHTOOL_MSG_RSS_CREATE_ACT`` create an additional RSS context
|
||||
``ETHTOOL_MSG_RSS_DELETE_ACT`` delete an additional RSS context
|
||||
===================================== =================================
|
||||
|
||||
Kernel to userspace:
|
||||
|
@ -297,6 +298,7 @@ Kernel to userspace:
|
|||
``ETHTOOL_MSG_RSS_NTF`` RSS settings notification
|
||||
``ETHTOOL_MSG_RSS_CREATE_ACT_REPLY`` create an additional RSS context
|
||||
``ETHTOOL_MSG_RSS_CREATE_NTF`` additional RSS context created
|
||||
``ETHTOOL_MSG_RSS_DELETE_NTF`` additional RSS context deleted
|
||||
======================================== =================================
|
||||
|
||||
``GET`` requests are sent by userspace applications to retrieve device
|
||||
|
@ -2041,6 +2043,18 @@ Kernel response contents:
|
|||
Create an additional RSS context, if ``ETHTOOL_A_RSS_CONTEXT`` is not
|
||||
specified kernel will allocate one automatically.
|
||||
|
||||
RSS_DELETE_ACT
|
||||
==============
|
||||
|
||||
Request contents:
|
||||
|
||||
===================================== ====== ==============================
|
||||
``ETHTOOL_A_RSS_HEADER`` nested request header
|
||||
``ETHTOOL_A_RSS_CONTEXT`` u32 context number
|
||||
===================================== ====== ==============================
|
||||
|
||||
Delete an additional RSS context.
|
||||
|
||||
PLCA_GET_CFG
|
||||
============
|
||||
|
||||
|
|
|
@ -842,6 +842,7 @@ enum {
|
|||
ETHTOOL_MSG_TSCONFIG_SET,
|
||||
ETHTOOL_MSG_RSS_SET,
|
||||
ETHTOOL_MSG_RSS_CREATE_ACT,
|
||||
ETHTOOL_MSG_RSS_DELETE_ACT,
|
||||
|
||||
__ETHTOOL_MSG_USER_CNT,
|
||||
ETHTOOL_MSG_USER_MAX = (__ETHTOOL_MSG_USER_CNT - 1)
|
||||
|
@ -901,6 +902,7 @@ enum {
|
|||
ETHTOOL_MSG_RSS_NTF,
|
||||
ETHTOOL_MSG_RSS_CREATE_ACT_REPLY,
|
||||
ETHTOOL_MSG_RSS_CREATE_NTF,
|
||||
ETHTOOL_MSG_RSS_DELETE_NTF,
|
||||
|
||||
__ETHTOOL_MSG_KERNEL_CNT,
|
||||
ETHTOOL_MSG_KERNEL_MAX = (__ETHTOOL_MSG_KERNEL_CNT - 1)
|
||||
|
|
|
@ -1136,5 +1136,6 @@ void ethtool_rxfh_context_lost(struct net_device *dev, u32 context_id)
|
|||
netdev_err(dev, "device error, RSS context %d lost\n", context_id);
|
||||
ctx = xa_erase(&dev->ethtool->rss_ctx, context_id);
|
||||
kfree(ctx);
|
||||
ethtool_rss_notify(dev, ETHTOOL_MSG_RSS_DELETE_NTF, context_id);
|
||||
}
|
||||
EXPORT_SYMBOL(ethtool_rxfh_context_lost);
|
||||
|
|
|
@ -1647,6 +1647,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
|
|||
!memchr_inv(ethtool_rxfh_context_key(ctx), 0,
|
||||
ctx->key_size));
|
||||
} else if (rxfh_dev.rss_delete) {
|
||||
ntf = ETHTOOL_MSG_RSS_DELETE_NTF;
|
||||
ret = ops->remove_rxfh_context(dev, ctx, rxfh.rss_context,
|
||||
extack);
|
||||
} else {
|
||||
|
|
|
@ -1527,6 +1527,13 @@ static const struct genl_ops ethtool_genl_ops[] = {
|
|||
.policy = ethnl_rss_create_policy,
|
||||
.maxattr = ARRAY_SIZE(ethnl_rss_create_policy) - 1,
|
||||
},
|
||||
{
|
||||
.cmd = ETHTOOL_MSG_RSS_DELETE_ACT,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.doit = ethnl_rss_delete_doit,
|
||||
.policy = ethnl_rss_delete_policy,
|
||||
.maxattr = ARRAY_SIZE(ethnl_rss_delete_policy) - 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
|
||||
|
|
|
@ -487,6 +487,7 @@ extern const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1];
|
|||
extern const struct nla_policy ethnl_rss_get_policy[ETHTOOL_A_RSS_START_CONTEXT + 1];
|
||||
extern const struct nla_policy ethnl_rss_set_policy[ETHTOOL_A_RSS_FLOW_HASH + 1];
|
||||
extern const struct nla_policy ethnl_rss_create_policy[ETHTOOL_A_RSS_INPUT_XFRM + 1];
|
||||
extern const struct nla_policy ethnl_rss_delete_policy[ETHTOOL_A_RSS_CONTEXT + 1];
|
||||
extern const struct nla_policy ethnl_plca_get_cfg_policy[ETHTOOL_A_PLCA_HEADER + 1];
|
||||
extern const struct nla_policy ethnl_plca_set_cfg_policy[ETHTOOL_A_PLCA_MAX + 1];
|
||||
extern const struct nla_policy ethnl_plca_get_status_policy[ETHTOOL_A_PLCA_HEADER + 1];
|
||||
|
@ -510,6 +511,7 @@ int ethnl_tsinfo_start(struct netlink_callback *cb);
|
|||
int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
|
||||
int ethnl_tsinfo_done(struct netlink_callback *cb);
|
||||
int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info);
|
||||
int ethnl_rss_delete_doit(struct sk_buff *skb, struct genl_info *info);
|
||||
|
||||
extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];
|
||||
extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];
|
||||
|
|
|
@ -486,12 +486,48 @@ int ethnl_rss_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
|
||||
/* RSS_NTF */
|
||||
|
||||
static void ethnl_rss_delete_notify(struct net_device *dev, u32 rss_context)
|
||||
{
|
||||
struct sk_buff *ntf;
|
||||
size_t ntf_size;
|
||||
void *hdr;
|
||||
|
||||
ntf_size = ethnl_reply_header_size() +
|
||||
nla_total_size(sizeof(u32)); /* _RSS_CONTEXT */
|
||||
|
||||
ntf = genlmsg_new(ntf_size, GFP_KERNEL);
|
||||
if (!ntf)
|
||||
goto out_warn;
|
||||
|
||||
hdr = ethnl_bcastmsg_put(ntf, ETHTOOL_MSG_RSS_DELETE_NTF);
|
||||
if (!hdr)
|
||||
goto out_free_ntf;
|
||||
|
||||
if (ethnl_fill_reply_header(ntf, dev, ETHTOOL_A_RSS_HEADER) ||
|
||||
nla_put_u32(ntf, ETHTOOL_A_RSS_CONTEXT, rss_context))
|
||||
goto out_free_ntf;
|
||||
|
||||
genlmsg_end(ntf, hdr);
|
||||
if (ethnl_multicast(ntf, dev))
|
||||
goto out_warn;
|
||||
|
||||
return;
|
||||
|
||||
out_free_ntf:
|
||||
nlmsg_free(ntf);
|
||||
out_warn:
|
||||
pr_warn_once("Failed to send a RSS delete notification");
|
||||
}
|
||||
|
||||
void ethtool_rss_notify(struct net_device *dev, u32 type, u32 rss_context)
|
||||
{
|
||||
struct rss_req_info req_info = {
|
||||
.rss_context = rss_context,
|
||||
};
|
||||
|
||||
if (type == ETHTOOL_MSG_RSS_DELETE_NTF)
|
||||
ethnl_rss_delete_notify(dev, rss_context);
|
||||
else
|
||||
ethnl_notify(dev, type, &req_info.base);
|
||||
}
|
||||
|
||||
|
@ -1096,3 +1132,74 @@ err_unlock_free_ctx:
|
|||
kfree(ctx);
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
/* RSS_DELETE */
|
||||
|
||||
const struct nla_policy ethnl_rss_delete_policy[ETHTOOL_A_RSS_CONTEXT + 1] = {
|
||||
[ETHTOOL_A_RSS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
|
||||
[ETHTOOL_A_RSS_CONTEXT] = NLA_POLICY_MIN(NLA_U32, 1),
|
||||
};
|
||||
|
||||
int ethnl_rss_delete_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct ethtool_rxfh_context *ctx;
|
||||
struct nlattr **tb = info->attrs;
|
||||
struct ethnl_req_info req = {};
|
||||
const struct ethtool_ops *ops;
|
||||
struct net_device *dev;
|
||||
u32 rss_context;
|
||||
int ret;
|
||||
|
||||
if (GENL_REQ_ATTR_CHECK(info, ETHTOOL_A_RSS_CONTEXT))
|
||||
return -EINVAL;
|
||||
rss_context = nla_get_u32(tb[ETHTOOL_A_RSS_CONTEXT]);
|
||||
|
||||
ret = ethnl_parse_header_dev_get(&req, tb[ETHTOOL_A_RSS_HEADER],
|
||||
genl_info_net(info), info->extack,
|
||||
true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev = req.dev;
|
||||
ops = dev->ethtool_ops;
|
||||
|
||||
if (!ops->create_rxfh_context)
|
||||
goto exit_free_dev;
|
||||
|
||||
rtnl_lock();
|
||||
netdev_lock_ops(dev);
|
||||
|
||||
ret = ethnl_ops_begin(dev);
|
||||
if (ret < 0)
|
||||
goto exit_dev_unlock;
|
||||
|
||||
mutex_lock(&dev->ethtool->rss_lock);
|
||||
ret = ethtool_check_rss_ctx_busy(dev, rss_context);
|
||||
if (ret)
|
||||
goto exit_unlock;
|
||||
|
||||
ctx = xa_load(&dev->ethtool->rss_ctx, rss_context);
|
||||
if (!ctx) {
|
||||
ret = -ENOENT;
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
ret = ops->remove_rxfh_context(dev, ctx, rss_context, info->extack);
|
||||
if (ret)
|
||||
goto exit_unlock;
|
||||
|
||||
WARN_ON(xa_erase(&dev->ethtool->rss_ctx, rss_context) != ctx);
|
||||
kfree(ctx);
|
||||
|
||||
ethnl_rss_delete_notify(dev, rss_context);
|
||||
|
||||
exit_unlock:
|
||||
mutex_unlock(&dev->ethtool->rss_lock);
|
||||
ethnl_ops_complete(dev);
|
||||
exit_dev_unlock:
|
||||
netdev_unlock_ops(dev);
|
||||
rtnl_unlock();
|
||||
exit_free_dev:
|
||||
ethnl_parse_header_dev_put(&req);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue