Commit ec6e57be authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

ethtool: rss: don't report key if device doesn't support it

marvell/otx2 and mvpp2 do not support setting different
keys for different RSS contexts. Contexts have separate
indirection tables but key is shared with all other contexts.
This is likely fine, indirection table is the most important
piece.

Don't report the key-related parameters from such drivers.
This prevents driver-errors, e.g. otx2 always writes
the main key, even when user asks to change per-context key.
The second reason is that without this change tracking
the keys by the core gets complicated. Even if the driver
correctly reject setting key with rss_context != 0,
change of the main key would have to be reflected in
the XArray for all additional contexts.

Since the additional contexts don't have their own keys
not including the attributes (in Netlink speak) seems
intuitive. ethtool CLI seems to deal with it just fine.

Having to set the flag in majority of the drivers is
a bit tedious but not reporting the key is a safer
default.
Reviewed-by: default avatarEdward Cree <ecree.xilinx@gmail.com>
Reviewed-by: default avatarJoe Damato <jdamato@fastly.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fb770fe7
...@@ -5289,6 +5289,7 @@ void bnxt_ethtool_free(struct bnxt *bp) ...@@ -5289,6 +5289,7 @@ void bnxt_ethtool_free(struct bnxt *bp)
const struct ethtool_ops bnxt_ethtool_ops = { const struct ethtool_ops bnxt_ethtool_ops = {
.cap_link_lanes_supported = 1, .cap_link_lanes_supported = 1,
.rxfh_per_ctx_key = 1,
.rxfh_max_num_contexts = BNXT_MAX_ETH_RSS_CTX + 1, .rxfh_max_num_contexts = BNXT_MAX_ETH_RSS_CTX + 1,
.rxfh_indir_space = BNXT_MAX_RSS_TABLE_ENTRIES_P5, .rxfh_indir_space = BNXT_MAX_RSS_TABLE_ENTRIES_P5,
.rxfh_priv_size = sizeof(struct bnxt_rss_ctx), .rxfh_priv_size = sizeof(struct bnxt_rss_ctx),
......
...@@ -4725,6 +4725,7 @@ static const struct ethtool_ops ice_ethtool_ops = { ...@@ -4725,6 +4725,7 @@ static const struct ethtool_ops ice_ethtool_ops = {
ETHTOOL_COALESCE_USE_ADAPTIVE | ETHTOOL_COALESCE_USE_ADAPTIVE |
ETHTOOL_COALESCE_RX_USECS_HIGH, ETHTOOL_COALESCE_RX_USECS_HIGH,
.cap_rss_sym_xor_supported = true, .cap_rss_sym_xor_supported = true,
.rxfh_per_ctx_key = true,
.get_link_ksettings = ice_get_link_ksettings, .get_link_ksettings = ice_get_link_ksettings,
.set_link_ksettings = ice_set_link_ksettings, .set_link_ksettings = ice_set_link_ksettings,
.get_fec_stats = ice_get_fec_stats, .get_fec_stats = ice_get_fec_stats,
......
...@@ -2595,6 +2595,7 @@ static void mlx5e_get_ts_stats(struct net_device *netdev, ...@@ -2595,6 +2595,7 @@ static void mlx5e_get_ts_stats(struct net_device *netdev,
const struct ethtool_ops mlx5e_ethtool_ops = { const struct ethtool_ops mlx5e_ethtool_ops = {
.cap_rss_ctx_supported = true, .cap_rss_ctx_supported = true,
.rxfh_per_ctx_key = true,
.supported_coalesce_params = ETHTOOL_COALESCE_USECS | .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES | ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE | ETHTOOL_COALESCE_USE_ADAPTIVE |
......
...@@ -58,6 +58,7 @@ const struct ethtool_ops ef100_ethtool_ops = { ...@@ -58,6 +58,7 @@ const struct ethtool_ops ef100_ethtool_ops = {
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
.get_rxfh_key_size = efx_ethtool_get_rxfh_key_size, .get_rxfh_key_size = efx_ethtool_get_rxfh_key_size,
.rxfh_per_ctx_key = true,
.rxfh_priv_size = sizeof(struct efx_rss_context_priv), .rxfh_priv_size = sizeof(struct efx_rss_context_priv),
.get_rxfh = efx_ethtool_get_rxfh, .get_rxfh = efx_ethtool_get_rxfh,
.set_rxfh = efx_ethtool_set_rxfh, .set_rxfh = efx_ethtool_set_rxfh,
......
...@@ -267,6 +267,7 @@ const struct ethtool_ops efx_ethtool_ops = { ...@@ -267,6 +267,7 @@ const struct ethtool_ops efx_ethtool_ops = {
.set_rxnfc = efx_ethtool_set_rxnfc, .set_rxnfc = efx_ethtool_set_rxnfc,
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
.get_rxfh_key_size = efx_ethtool_get_rxfh_key_size, .get_rxfh_key_size = efx_ethtool_get_rxfh_key_size,
.rxfh_per_ctx_key = true,
.rxfh_priv_size = sizeof(struct efx_rss_context_priv), .rxfh_priv_size = sizeof(struct efx_rss_context_priv),
.get_rxfh = efx_ethtool_get_rxfh, .get_rxfh = efx_ethtool_get_rxfh,
.set_rxfh = efx_ethtool_set_rxfh, .set_rxfh = efx_ethtool_set_rxfh,
......
...@@ -731,6 +731,9 @@ struct kernel_ethtool_ts_info { ...@@ -731,6 +731,9 @@ struct kernel_ethtool_ts_info {
* do not have to set this bit. * do not have to set this bit.
* @cap_rss_sym_xor_supported: indicates if the driver supports symmetric-xor * @cap_rss_sym_xor_supported: indicates if the driver supports symmetric-xor
* RSS. * RSS.
* @rxfh_per_ctx_key: device supports setting different RSS key for each
* additional context. Netlink API should report hfunc, key, and input_xfrm
* for every context, not just context 0.
* @rxfh_indir_space: max size of RSS indirection tables, if indirection table * @rxfh_indir_space: max size of RSS indirection tables, if indirection table
* size as returned by @get_rxfh_indir_size may change during lifetime * size as returned by @get_rxfh_indir_size may change during lifetime
* of the device. Leave as 0 if the table size is constant. * of the device. Leave as 0 if the table size is constant.
...@@ -952,6 +955,7 @@ struct ethtool_ops { ...@@ -952,6 +955,7 @@ struct ethtool_ops {
u32 cap_link_lanes_supported:1; u32 cap_link_lanes_supported:1;
u32 cap_rss_ctx_supported:1; u32 cap_rss_ctx_supported:1;
u32 cap_rss_sym_xor_supported:1; u32 cap_rss_sym_xor_supported:1;
u32 rxfh_per_ctx_key:1;
u32 rxfh_indir_space; u32 rxfh_indir_space;
u16 rxfh_key_space; u16 rxfh_key_space;
u16 rxfh_priv_size; u16 rxfh_priv_size;
......
...@@ -1261,10 +1261,15 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev, ...@@ -1261,10 +1261,15 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
if (rxfh_dev.indir) if (rxfh_dev.indir)
memcpy(rxfh_dev.indir, ethtool_rxfh_context_indir(ctx), memcpy(rxfh_dev.indir, ethtool_rxfh_context_indir(ctx),
indir_bytes); indir_bytes);
if (rxfh_dev.key) if (!ops->rxfh_per_ctx_key) {
memcpy(rxfh_dev.key, ethtool_rxfh_context_key(ctx), rxfh_dev.key_size = 0;
user_key_size); } else {
rxfh_dev.hfunc = ctx->hfunc; if (rxfh_dev.key)
memcpy(rxfh_dev.key,
ethtool_rxfh_context_key(ctx),
user_key_size);
rxfh_dev.hfunc = ctx->hfunc;
}
rxfh_dev.input_xfrm = ctx->input_xfrm; rxfh_dev.input_xfrm = ctx->input_xfrm;
ret = 0; ret = 0;
} else { } else {
...@@ -1281,6 +1286,11 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev, ...@@ -1281,6 +1286,11 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
&rxfh_dev.input_xfrm, &rxfh_dev.input_xfrm,
sizeof(rxfh.input_xfrm))) { sizeof(rxfh.input_xfrm))) {
ret = -EFAULT; ret = -EFAULT;
} else if (copy_to_user(useraddr +
offsetof(struct ethtool_rxfh, key_size),
&rxfh_dev.key_size,
sizeof(rxfh.key_size))) {
ret = -EFAULT;
} else if (copy_to_user(useraddr + } else if (copy_to_user(useraddr +
offsetof(struct ethtool_rxfh, rss_config[0]), offsetof(struct ethtool_rxfh, rss_config[0]),
rss_config, total_size)) { rss_config, total_size)) {
...@@ -1389,6 +1399,13 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, ...@@ -1389,6 +1399,13 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
indir_bytes = dev_indir_size * sizeof(rxfh_dev.indir[0]); indir_bytes = dev_indir_size * sizeof(rxfh_dev.indir[0]);
/* Check settings which may be global rather than per RSS-context */
if (rxfh.rss_context && !ops->rxfh_per_ctx_key)
if (rxfh.key_size ||
(rxfh.hfunc && rxfh.hfunc != ETH_RSS_HASH_NO_CHANGE) ||
(rxfh.input_xfrm && rxfh.input_xfrm != RXH_XFRM_NO_CHANGE))
return -EOPNOTSUPP;
rss_config = kzalloc(indir_bytes + dev_key_size, GFP_USER); rss_config = kzalloc(indir_bytes + dev_key_size, GFP_USER);
if (!rss_config) if (!rss_config)
return -ENOMEM; return -ENOMEM;
......
...@@ -10,6 +10,7 @@ struct rss_req_info { ...@@ -10,6 +10,7 @@ struct rss_req_info {
struct rss_reply_data { struct rss_reply_data {
struct ethnl_reply_data base; struct ethnl_reply_data base;
bool no_key_fields;
u32 indir_size; u32 indir_size;
u32 hkey_size; u32 hkey_size;
u32 hfunc; u32 hfunc;
...@@ -60,9 +61,12 @@ rss_prepare_data(const struct ethnl_req_info *req_base, ...@@ -60,9 +61,12 @@ rss_prepare_data(const struct ethnl_req_info *req_base,
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* Some drivers don't handle rss_context */ /* Some drivers don't handle rss_context */
if (request->rss_context && !(ops->cap_rss_ctx_supported || if (request->rss_context) {
ops->create_rxfh_context)) if (!ops->cap_rss_ctx_supported && !ops->create_rxfh_context)
return -EOPNOTSUPP; return -EOPNOTSUPP;
data->no_key_fields = !ops->rxfh_per_ctx_key;
}
ret = ethnl_ops_begin(dev); ret = ethnl_ops_begin(dev);
if (ret < 0) if (ret < 0)
...@@ -132,13 +136,18 @@ rss_fill_reply(struct sk_buff *skb, const struct ethnl_req_info *req_base, ...@@ -132,13 +136,18 @@ rss_fill_reply(struct sk_buff *skb, const struct ethnl_req_info *req_base,
nla_put_u32(skb, ETHTOOL_A_RSS_CONTEXT, request->rss_context)) nla_put_u32(skb, ETHTOOL_A_RSS_CONTEXT, request->rss_context))
return -EMSGSIZE; return -EMSGSIZE;
if ((data->indir_size &&
nla_put(skb, ETHTOOL_A_RSS_INDIR,
sizeof(u32) * data->indir_size, data->indir_table)))
return -EMSGSIZE;
if (data->no_key_fields)
return 0;
if ((data->hfunc && if ((data->hfunc &&
nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc)) || nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc)) ||
(data->input_xfrm && (data->input_xfrm &&
nla_put_u32(skb, ETHTOOL_A_RSS_INPUT_XFRM, data->input_xfrm)) || nla_put_u32(skb, ETHTOOL_A_RSS_INPUT_XFRM, data->input_xfrm)) ||
(data->indir_size &&
nla_put(skb, ETHTOOL_A_RSS_INDIR,
sizeof(u32) * data->indir_size, data->indir_table)) ||
(data->hkey_size && (data->hkey_size &&
nla_put(skb, ETHTOOL_A_RSS_HKEY, data->hkey_size, data->hkey))) nla_put(skb, ETHTOOL_A_RSS_HKEY, data->hkey_size, data->hkey)))
return -EMSGSIZE; return -EMSGSIZE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment