Skip to content

Commit d3e2c7b

Browse files
committed
ethtool: rss: support setting input-xfrm via Netlink
Support configuring symmetric hashing via Netlink. We have the flow field config prepared as part of SET handling, so scan it for conflicts instead of querying the driver again. Reviewed-by: Gal Pressman <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent c1b27f0 commit d3e2c7b

File tree

6 files changed

+71
-8
lines changed

6 files changed

+71
-8
lines changed

Documentation/netlink/specs/ethtool.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2678,6 +2678,7 @@ operations:
26782678
- hfunc
26792679
- indir
26802680
- hkey
2681+
- input-xfrm
26812682
-
26822683
name: rss-ntf
26832684
doc: |

Documentation/networking/ethtool-netlink.rst

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,6 +2002,7 @@ Request contents:
20022002
``ETHTOOL_A_RSS_HFUNC`` u32 RSS hash func
20032003
``ETHTOOL_A_RSS_INDIR`` binary Indir table bytes
20042004
``ETHTOOL_A_RSS_HKEY`` binary Hash key bytes
2005+
``ETHTOOL_A_RSS_INPUT_XFRM`` u32 RSS input data transformation
20052006
===================================== ====== ==============================
20062007

20072008
``ETHTOOL_A_RSS_INDIR`` is the minimal RSS table the user expects. Kernel and
@@ -2012,9 +2013,6 @@ device needs at least 8 entries - the real table in use will end up being
20122013
of 2, so tables which size is not a power of 2 will likely be rejected.
20132014
Using table of size 0 will reset the indirection table to the default.
20142015

2015-
Note that, at present, only a subset of RSS configuration can be accomplished
2016-
over Netlink.
2017-
20182016
PLCA_GET_CFG
20192017
============
20202018

net/ethtool/common.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,21 @@ int ethtool_check_rss_ctx_busy(struct net_device *dev, u32 rss_context)
806806
return rc;
807807
}
808808

809+
/* Check if fields configured for flow hash are symmetric - if src is included
810+
* so is dst and vice versa.
811+
*/
812+
int ethtool_rxfh_config_is_sym(u64 rxfh)
813+
{
814+
bool sym;
815+
816+
sym = rxfh == (rxfh & (RXH_IP_SRC | RXH_IP_DST |
817+
RXH_L4_B_0_1 | RXH_L4_B_2_3));
818+
sym &= !!(rxfh & RXH_IP_SRC) == !!(rxfh & RXH_IP_DST);
819+
sym &= !!(rxfh & RXH_L4_B_0_1) == !!(rxfh & RXH_L4_B_2_3);
820+
821+
return sym;
822+
}
823+
809824
int ethtool_check_ops(const struct ethtool_ops *ops)
810825
{
811826
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
@@ -44,6 +44,7 @@ int ethtool_check_max_channel(struct net_device *dev,
4444
struct ethtool_channels channels,
4545
struct genl_info *info);
4646
int ethtool_check_rss_ctx_busy(struct net_device *dev, u32 rss_context);
47+
int ethtool_rxfh_config_is_sym(u64 rxfh);
4748

4849
void ethtool_ringparam_get_cfg(struct net_device *dev,
4950
struct ethtool_ringparam *param,

net/ethtool/ioctl.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,9 +1027,7 @@ static int ethtool_check_xfrm_rxfh(u32 input_xfrm, u64 rxfh)
10271027
*/
10281028
if ((input_xfrm != RXH_XFRM_NO_CHANGE &&
10291029
input_xfrm & (RXH_XFRM_SYM_XOR | RXH_XFRM_SYM_OR_XOR)) &&
1030-
((rxfh & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)) ||
1031-
(!!(rxfh & RXH_IP_SRC) ^ !!(rxfh & RXH_IP_DST)) ||
1032-
(!!(rxfh & RXH_L4_B_0_1) ^ !!(rxfh & RXH_L4_B_2_3))))
1030+
!ethtool_rxfh_config_is_sym(rxfh))
10331031
return -EINVAL;
10341032

10351033
return 0;

net/ethtool/rss.c

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,8 @@ const struct nla_policy ethnl_rss_set_policy[ETHTOOL_A_RSS_START_CONTEXT + 1] =
478478
[ETHTOOL_A_RSS_HFUNC] = NLA_POLICY_MIN(NLA_U32, 1),
479479
[ETHTOOL_A_RSS_INDIR] = { .type = NLA_BINARY, },
480480
[ETHTOOL_A_RSS_HKEY] = NLA_POLICY_MIN(NLA_BINARY, 1),
481+
[ETHTOOL_A_RSS_INPUT_XFRM] =
482+
NLA_POLICY_MAX(NLA_U32, RXH_XFRM_SYM_OR_XOR),
481483
};
482484

483485
static int
@@ -487,15 +489,21 @@ ethnl_rss_set_validate(struct ethnl_req_info *req_info, struct genl_info *info)
487489
struct rss_req_info *request = RSS_REQINFO(req_info);
488490
struct nlattr **tb = info->attrs;
489491
struct nlattr *bad_attr = NULL;
492+
u32 input_xfrm;
490493

491494
if (request->rss_context && !ops->create_rxfh_context)
492495
bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_CONTEXT];
493496

494497
if (request->rss_context && !ops->rxfh_per_ctx_key) {
495498
bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_HFUNC];
496499
bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_HKEY];
500+
bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_INPUT_XFRM];
497501
}
498502

503+
input_xfrm = nla_get_u32_default(tb[ETHTOOL_A_RSS_INPUT_XFRM], 0);
504+
if (input_xfrm & ~ops->supported_input_xfrm)
505+
bad_attr = bad_attr ?: tb[ETHTOOL_A_RSS_INPUT_XFRM];
506+
499507
if (bad_attr) {
500508
NL_SET_BAD_ATTR(info->extack, bad_attr);
501509
return -EOPNOTSUPP;
@@ -609,6 +617,33 @@ rss_set_prep_hkey(struct net_device *dev, struct genl_info *info,
609617
return 0;
610618
}
611619

620+
static int
621+
rss_check_rxfh_fields_sym(struct net_device *dev, struct genl_info *info,
622+
struct rss_reply_data *data, bool xfrm_sym)
623+
{
624+
struct nlattr **tb = info->attrs;
625+
int i;
626+
627+
if (!xfrm_sym)
628+
return 0;
629+
if (!data->has_flow_hash) {
630+
NL_SET_ERR_MSG_ATTR(info->extack, tb[ETHTOOL_A_RSS_INPUT_XFRM],
631+
"hash field config not reported");
632+
return -EINVAL;
633+
}
634+
635+
for (i = 1; i < __ETHTOOL_A_FLOW_CNT; i++)
636+
if (data->flow_hash[i] >= 0 &&
637+
!ethtool_rxfh_config_is_sym(data->flow_hash[i])) {
638+
NL_SET_ERR_MSG_ATTR(info->extack,
639+
tb[ETHTOOL_A_RSS_INPUT_XFRM],
640+
"hash field config is not symmetric");
641+
return -EINVAL;
642+
}
643+
644+
return 0;
645+
}
646+
612647
static void
613648
rss_set_ctx_update(struct ethtool_rxfh_context *ctx, struct nlattr **tb,
614649
struct rss_reply_data *data, struct ethtool_rxfh_param *rxfh)
@@ -627,16 +662,18 @@ rss_set_ctx_update(struct ethtool_rxfh_context *ctx, struct nlattr **tb,
627662
}
628663
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE)
629664
ctx->hfunc = rxfh->hfunc;
665+
if (rxfh->input_xfrm != RXH_XFRM_NO_CHANGE)
666+
ctx->input_xfrm = rxfh->input_xfrm;
630667
}
631668

632669
static int
633670
ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
634671
{
672+
bool indir_reset = false, indir_mod, xfrm_sym = false;
635673
struct rss_req_info *request = RSS_REQINFO(req_info);
636674
struct ethtool_rxfh_context *ctx = NULL;
637675
struct net_device *dev = req_info->dev;
638676
struct ethtool_rxfh_param rxfh = {};
639-
bool indir_reset = false, indir_mod;
640677
struct nlattr **tb = info->attrs;
641678
struct rss_reply_data data = {};
642679
const struct ethtool_ops *ops;
@@ -666,7 +703,20 @@ ethnl_rss_set(struct ethnl_req_info *req_info, struct genl_info *info)
666703
if (ret)
667704
goto exit_free_indir;
668705

669-
rxfh.input_xfrm = RXH_XFRM_NO_CHANGE;
706+
rxfh.input_xfrm = data.input_xfrm;
707+
ethnl_update_u8(&rxfh.input_xfrm, tb[ETHTOOL_A_RSS_INPUT_XFRM], &mod);
708+
/* For drivers which don't support input_xfrm it will be set to 0xff
709+
* in the RSS context info. In all other case input_xfrm != 0 means
710+
* symmetric hashing is requested.
711+
*/
712+
if (!request->rss_context || ops->rxfh_per_ctx_key)
713+
xfrm_sym = !!rxfh.input_xfrm;
714+
if (rxfh.input_xfrm == data.input_xfrm)
715+
rxfh.input_xfrm = RXH_XFRM_NO_CHANGE;
716+
717+
ret = rss_check_rxfh_fields_sym(dev, info, &data, xfrm_sym);
718+
if (ret)
719+
goto exit_clean_data;
670720

671721
mutex_lock(&dev->ethtool->rss_lock);
672722
if (request->rss_context) {

0 commit comments

Comments
 (0)