Commit 82ae67cb authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

ethtool: rss: support setting hfunc via Netlink



Support setting RSS hash function / algo via ethtool Netlink.
Like IOCTL we don't validate that the function is within the
range known to the kernel. The drivers do a pretty good job
validating the inputs, and the IDs are technically "dynamically
queried" rather than part of uAPI.

Only change should be that in Netlink we don't support user
explicitly passing ETH_RSS_HASH_NO_CHANGE (0), if no change
is requested the attribute should be absent.

The ETH_RSS_HASH_NO_CHANGE is retained in driver-facing
API for consistency (not that I see a strong reason for it).

Reviewed-by: default avatarGal Pressman <gal@nvidia.com>
Link: https://patch.msgid.link/20250716000331.1378807-6-kuba@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 6e7eb93a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2654,6 +2654,7 @@ operations:
          attributes:
            - header
            - context
            - hfunc
            - indir
    -
      name: rss-ntf
+1 −0
Original line number Diff line number Diff line
@@ -1999,6 +1999,7 @@ Request contents:
=====================================  ======  ==============================
  ``ETHTOOL_A_RSS_HEADER``             nested  request header
  ``ETHTOOL_A_RSS_CONTEXT``            u32     context number
  ``ETHTOOL_A_RSS_HFUNC``              u32     RSS hash func
  ``ETHTOOL_A_RSS_INDIR``              binary  Indir table bytes
=====================================  ======  ==============================

+11 −1
Original line number Diff line number Diff line
@@ -475,6 +475,7 @@ void ethtool_rss_notify(struct net_device *dev, u32 rss_context)
const struct nla_policy ethnl_rss_set_policy[ETHTOOL_A_RSS_START_CONTEXT + 1] = {
	[ETHTOOL_A_RSS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
	[ETHTOOL_A_RSS_CONTEXT] = { .type = NLA_U32, },
	[ETHTOOL_A_RSS_HFUNC] = NLA_POLICY_MIN(NLA_U32, 1),
	[ETHTOOL_A_RSS_INDIR] = { .type = NLA_BINARY, },
};

@@ -489,6 +490,9 @@ ethnl_rss_set_validate(struct ethnl_req_info *req_info, struct genl_info *info)
	if (request->rss_context && !ops->create_rxfh_context)
		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_CONTEXT];

	if (request->rss_context && !ops->rxfh_per_ctx_key)
		bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_HFUNC];

	if (bad_attr) {
		NL_SET_BAD_ATTR(info->extack, bad_attr);
		return -EOPNOTSUPP;
@@ -588,6 +592,8 @@ rss_set_ctx_update(struct ethtool_rxfh_context *ctx, struct nlattr **tb,
			ethtool_rxfh_context_indir(ctx)[i] = rxfh->indir[i];
		ctx->indir_configured = !!nla_len(tb[ETHTOOL_A_RSS_INDIR]);
	}
	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE)
		ctx->hfunc = rxfh->hfunc;
}

static int
@@ -618,7 +624,11 @@ ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
		goto exit_clean_data;
	indir_mod = !!tb[ETHTOOL_A_RSS_INDIR];

	rxfh.hfunc = data.hfunc;
	ethnl_update_u8(&rxfh.hfunc, tb[ETHTOOL_A_RSS_HFUNC], &mod);
	if (rxfh.hfunc == data.hfunc)
		rxfh.hfunc = ETH_RSS_HASH_NO_CHANGE;

	rxfh.input_xfrm = RXH_XFRM_NO_CHANGE;

	mutex_lock(&dev->ethtool->rss_lock);