Skip to content

Commit

Permalink
ethtool: rss: prevent rss ctx deletion when in use
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Daniel Zahka authored and Paolo Abeni committed Oct 17, 2024
1 parent 5cb409b commit 42dc431
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
48 changes: 48 additions & 0 deletions net/ethtool/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
1 change: 1 addition & 0 deletions net/ethtool/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions net/ethtool/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 42dc431

Please sign in to comment.