Skip to content

Commit 42dc431

Browse files
Daniel ZahkaPaolo Abeni
authored andcommitted
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 <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 5cb409b commit 42dc431

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

net/ethtool/common.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,54 @@ int ethtool_check_max_channel(struct net_device *dev,
684684
return 0;
685685
}
686686

687+
int ethtool_check_rss_ctx_busy(struct net_device *dev, u32 rss_context)
688+
{
689+
const struct ethtool_ops *ops = dev->ethtool_ops;
690+
struct ethtool_rxnfc *info;
691+
int rc, i, rule_cnt;
692+
693+
if (!ops->get_rxnfc)
694+
return 0;
695+
696+
rule_cnt = ethtool_get_rxnfc_rule_count(dev);
697+
if (!rule_cnt)
698+
return 0;
699+
700+
if (rule_cnt < 0)
701+
return -EINVAL;
702+
703+
info = kvzalloc(struct_size(info, rule_locs, rule_cnt), GFP_KERNEL);
704+
if (!info)
705+
return -ENOMEM;
706+
707+
info->cmd = ETHTOOL_GRXCLSRLALL;
708+
info->rule_cnt = rule_cnt;
709+
rc = ops->get_rxnfc(dev, info, info->rule_locs);
710+
if (rc)
711+
goto out_free;
712+
713+
for (i = 0; i < rule_cnt; i++) {
714+
struct ethtool_rxnfc rule_info = {
715+
.cmd = ETHTOOL_GRXCLSRULE,
716+
.fs.location = info->rule_locs[i],
717+
};
718+
719+
rc = ops->get_rxnfc(dev, &rule_info, NULL);
720+
if (rc)
721+
goto out_free;
722+
723+
if (rule_info.fs.flow_type & FLOW_RSS &&
724+
rule_info.rss_context == rss_context) {
725+
rc = -EBUSY;
726+
goto out_free;
727+
}
728+
}
729+
730+
out_free:
731+
kvfree(info);
732+
return rc;
733+
}
734+
687735
int ethtool_check_ops(const struct ethtool_ops *ops)
688736
{
689737
if (WARN_ON(ops->set_coalesce && !ops->supported_coalesce_params))

net/ethtool/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ bool convert_legacy_settings_to_link_ksettings(
4747
int ethtool_check_max_channel(struct net_device *dev,
4848
struct ethtool_channels channels,
4949
struct genl_info *info);
50+
int ethtool_check_rss_ctx_busy(struct net_device *dev, u32 rss_context);
5051
int __ethtool_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info *info);
5152

5253
extern const struct ethtool_phy_ops *ethtool_phy_ops;

net/ethtool/ioctl.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,13 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
14621462
mutex_lock(&dev->ethtool->rss_lock);
14631463
locked = true;
14641464
}
1465+
1466+
if (rxfh.rss_context && rxfh_dev.rss_delete) {
1467+
ret = ethtool_check_rss_ctx_busy(dev, rxfh.rss_context);
1468+
if (ret)
1469+
goto out;
1470+
}
1471+
14651472
if (create) {
14661473
if (rxfh_dev.rss_delete) {
14671474
ret = -EINVAL;

0 commit comments

Comments
 (0)