Skip to content

Commit 51798c5

Browse files
committed
ethtool: rss: support setting hkey via Netlink
Support setting RSS hashing key via ethtool Netlink. Use the Netlink policy to make sure user doesn't pass an empty key, "resetting" the key is not a thing. Reviewed-by: Gal Pressman <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 82ae67c commit 51798c5

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

Documentation/netlink/specs/ethtool.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2656,6 +2656,7 @@ operations:
26562656
- context
26572657
- hfunc
26582658
- indir
2659+
- hkey
26592660
-
26602661
name: rss-ntf
26612662
doc: |

Documentation/networking/ethtool-netlink.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,6 +2001,7 @@ Request contents:
20012001
``ETHTOOL_A_RSS_CONTEXT`` u32 context number
20022002
``ETHTOOL_A_RSS_HFUNC`` u32 RSS hash func
20032003
``ETHTOOL_A_RSS_INDIR`` binary Indir table bytes
2004+
``ETHTOOL_A_RSS_HKEY`` binary Hash key bytes
20042005
===================================== ====== ==============================
20052006

20062007
``ETHTOOL_A_RSS_INDIR`` is the minimal RSS table the user expects. Kernel and

net/ethtool/rss.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ const struct nla_policy ethnl_rss_set_policy[ETHTOOL_A_RSS_START_CONTEXT + 1] =
477477
[ETHTOOL_A_RSS_CONTEXT] = { .type = NLA_U32, },
478478
[ETHTOOL_A_RSS_HFUNC] = NLA_POLICY_MIN(NLA_U32, 1),
479479
[ETHTOOL_A_RSS_INDIR] = { .type = NLA_BINARY, },
480+
[ETHTOOL_A_RSS_HKEY] = NLA_POLICY_MIN(NLA_BINARY, 1),
480481
};
481482

482483
static int
@@ -490,8 +491,10 @@ ethnl_rss_set_validate(struct ethnl_req_info *req_info, struct genl_info *info)
490491
if (request->rss_context && !ops->create_rxfh_context)
491492
bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_CONTEXT];
492493

493-
if (request->rss_context && !ops->rxfh_per_ctx_key)
494+
if (request->rss_context && !ops->rxfh_per_ctx_key) {
494495
bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_HFUNC];
496+
bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_HKEY];
497+
}
495498

496499
if (bad_attr) {
497500
NL_SET_BAD_ATTR(info->extack, bad_attr);
@@ -581,6 +584,31 @@ rss_set_prep_indir(struct net_device *dev, struct genl_info *info,
581584
return err;
582585
}
583586

587+
static int
588+
rss_set_prep_hkey(struct net_device *dev, struct genl_info *info,
589+
struct rss_reply_data *data, struct ethtool_rxfh_param *rxfh,
590+
bool *mod)
591+
{
592+
struct nlattr **tb = info->attrs;
593+
594+
if (!tb[ETHTOOL_A_RSS_HKEY])
595+
return 0;
596+
597+
if (nla_len(tb[ETHTOOL_A_RSS_HKEY]) != data->hkey_size) {
598+
NL_SET_BAD_ATTR(info->extack, tb[ETHTOOL_A_RSS_HKEY]);
599+
return -EINVAL;
600+
}
601+
602+
rxfh->key_size = data->hkey_size;
603+
rxfh->key = kmemdup(data->hkey, data->hkey_size, GFP_KERNEL);
604+
if (!rxfh->key)
605+
return -ENOMEM;
606+
607+
ethnl_update_binary(rxfh->key, rxfh->key_size, tb[ETHTOOL_A_RSS_HKEY],
608+
mod);
609+
return 0;
610+
}
611+
584612
static void
585613
rss_set_ctx_update(struct ethtool_rxfh_context *ctx, struct nlattr **tb,
586614
struct rss_reply_data *data, struct ethtool_rxfh_param *rxfh)
@@ -592,6 +620,11 @@ rss_set_ctx_update(struct ethtool_rxfh_context *ctx, struct nlattr **tb,
592620
ethtool_rxfh_context_indir(ctx)[i] = rxfh->indir[i];
593621
ctx->indir_configured = !!nla_len(tb[ETHTOOL_A_RSS_INDIR]);
594622
}
623+
if (rxfh->key) {
624+
memcpy(ethtool_rxfh_context_key(ctx), rxfh->key,
625+
data->hkey_size);
626+
ctx->key_configured = !!rxfh->key_size;
627+
}
595628
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE)
596629
ctx->hfunc = rxfh->hfunc;
597630
}
@@ -629,6 +662,10 @@ ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
629662
if (rxfh.hfunc == data.hfunc)
630663
rxfh.hfunc = ETH_RSS_HASH_NO_CHANGE;
631664

665+
ret = rss_set_prep_hkey(dev, info, &data, &rxfh, &mod);
666+
if (ret)
667+
goto exit_free_indir;
668+
632669
rxfh.input_xfrm = RXH_XFRM_NO_CHANGE;
633670

634671
mutex_lock(&dev->ethtool->rss_lock);
@@ -660,6 +697,8 @@ ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
660697

661698
exit_unlock:
662699
mutex_unlock(&dev->ethtool->rss_lock);
700+
kfree(rxfh.key);
701+
exit_free_indir:
663702
kfree(rxfh.indir);
664703
exit_clean_data:
665704
rss_cleanup_data(&data.base);

0 commit comments

Comments
 (0)