mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-19 14:56:21 +00:00
ethtool: rss: prevent rss ctx deletion when in use
ntuple filters can specify an rss context to use for packet hashing and queue selection. When a filter is referencing an rss context, it should be invalid for that context to be deleted. A list of active ntuple filters and their associated rss contexts can be compiled by querying a device's ethtool_ops.get_rxnfc. This patch checks to see if any ntuple filters are referencing an rss context during context deletion, and prevents the deletion if the requested context is still in use. Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
5cb409b396
commit
42dc431f5d
@ -684,6 +684,54 @@ int ethtool_check_max_channel(struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ethtool_check_rss_ctx_busy(struct net_device *dev, u32 rss_context)
|
||||
{
|
||||
const struct ethtool_ops *ops = dev->ethtool_ops;
|
||||
struct ethtool_rxnfc *info;
|
||||
int rc, i, rule_cnt;
|
||||
|
||||
if (!ops->get_rxnfc)
|
||||
return 0;
|
||||
|
||||
rule_cnt = ethtool_get_rxnfc_rule_count(dev);
|
||||
if (!rule_cnt)
|
||||
return 0;
|
||||
|
||||
if (rule_cnt < 0)
|
||||
return -EINVAL;
|
||||
|
||||
info = kvzalloc(struct_size(info, rule_locs, rule_cnt), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
info->cmd = ETHTOOL_GRXCLSRLALL;
|
||||
info->rule_cnt = rule_cnt;
|
||||
rc = ops->get_rxnfc(dev, info, info->rule_locs);
|
||||
if (rc)
|
||||
goto out_free;
|
||||
|
||||
for (i = 0; i < rule_cnt; i++) {
|
||||
struct ethtool_rxnfc rule_info = {
|
||||
.cmd = ETHTOOL_GRXCLSRULE,
|
||||
.fs.location = info->rule_locs[i],
|
||||
};
|
||||
|
||||
rc = ops->get_rxnfc(dev, &rule_info, NULL);
|
||||
if (rc)
|
||||
goto out_free;
|
||||
|
||||
if (rule_info.fs.flow_type & FLOW_RSS &&
|
||||
rule_info.rss_context == rss_context) {
|
||||
rc = -EBUSY;
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
out_free:
|
||||
kvfree(info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ethtool_check_ops(const struct ethtool_ops *ops)
|
||||
{
|
||||
if (WARN_ON(ops->set_coalesce && !ops->supported_coalesce_params))
|
||||
|
@ -47,6 +47,7 @@ bool convert_legacy_settings_to_link_ksettings(
|
||||
int ethtool_check_max_channel(struct net_device *dev,
|
||||
struct ethtool_channels channels,
|
||||
struct genl_info *info);
|
||||
int ethtool_check_rss_ctx_busy(struct net_device *dev, u32 rss_context);
|
||||
int __ethtool_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info *info);
|
||||
|
||||
extern const struct ethtool_phy_ops *ethtool_phy_ops;
|
||||
|
@ -1462,6 +1462,13 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
|
||||
mutex_lock(&dev->ethtool->rss_lock);
|
||||
locked = true;
|
||||
}
|
||||
|
||||
if (rxfh.rss_context && rxfh_dev.rss_delete) {
|
||||
ret = ethtool_check_rss_ctx_busy(dev, rxfh.rss_context);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (create) {
|
||||
if (rxfh_dev.rss_delete) {
|
||||
ret = -EINVAL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user