Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Edward Cree <ecree.xilinx@gmail.com>
Reviewed-by: Joe Damato <jdamato@fastly.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jakub Kicinski and committed by
David S. Miller
ec6e57be fb770fe7

+45 -10
+1
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
··· 5289 5289 5290 5290 const struct ethtool_ops bnxt_ethtool_ops = { 5291 5291 .cap_link_lanes_supported = 1, 5292 + .rxfh_per_ctx_key = 1, 5292 5293 .rxfh_max_num_contexts = BNXT_MAX_ETH_RSS_CTX + 1, 5293 5294 .rxfh_indir_space = BNXT_MAX_RSS_TABLE_ENTRIES_P5, 5294 5295 .rxfh_priv_size = sizeof(struct bnxt_rss_ctx),
+1
drivers/net/ethernet/intel/ice/ice_ethtool.c
··· 4725 4725 ETHTOOL_COALESCE_USE_ADAPTIVE | 4726 4726 ETHTOOL_COALESCE_RX_USECS_HIGH, 4727 4727 .cap_rss_sym_xor_supported = true, 4728 + .rxfh_per_ctx_key = true, 4728 4729 .get_link_ksettings = ice_get_link_ksettings, 4729 4730 .set_link_ksettings = ice_set_link_ksettings, 4730 4731 .get_fec_stats = ice_get_fec_stats,
+1
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
··· 2595 2595 2596 2596 const struct ethtool_ops mlx5e_ethtool_ops = { 2597 2597 .cap_rss_ctx_supported = true, 2598 + .rxfh_per_ctx_key = true, 2598 2599 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 2599 2600 ETHTOOL_COALESCE_MAX_FRAMES | 2600 2601 ETHTOOL_COALESCE_USE_ADAPTIVE |
+1
drivers/net/ethernet/sfc/ef100_ethtool.c
··· 58 58 59 59 .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, 60 60 .get_rxfh_key_size = efx_ethtool_get_rxfh_key_size, 61 + .rxfh_per_ctx_key = true, 61 62 .rxfh_priv_size = sizeof(struct efx_rss_context_priv), 62 63 .get_rxfh = efx_ethtool_get_rxfh, 63 64 .set_rxfh = efx_ethtool_set_rxfh,
+1
drivers/net/ethernet/sfc/ethtool.c
··· 267 267 .set_rxnfc = efx_ethtool_set_rxnfc, 268 268 .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, 269 269 .get_rxfh_key_size = efx_ethtool_get_rxfh_key_size, 270 + .rxfh_per_ctx_key = true, 270 271 .rxfh_priv_size = sizeof(struct efx_rss_context_priv), 271 272 .get_rxfh = efx_ethtool_get_rxfh, 272 273 .set_rxfh = efx_ethtool_set_rxfh,
+4
include/linux/ethtool.h
··· 731 731 * do not have to set this bit. 732 732 * @cap_rss_sym_xor_supported: indicates if the driver supports symmetric-xor 733 733 * RSS. 734 + * @rxfh_per_ctx_key: device supports setting different RSS key for each 735 + * additional context. Netlink API should report hfunc, key, and input_xfrm 736 + * for every context, not just context 0. 734 737 * @rxfh_indir_space: max size of RSS indirection tables, if indirection table 735 738 * size as returned by @get_rxfh_indir_size may change during lifetime 736 739 * of the device. Leave as 0 if the table size is constant. ··· 955 952 u32 cap_link_lanes_supported:1; 956 953 u32 cap_rss_ctx_supported:1; 957 954 u32 cap_rss_sym_xor_supported:1; 955 + u32 rxfh_per_ctx_key:1; 958 956 u32 rxfh_indir_space; 959 957 u16 rxfh_key_space; 960 958 u16 rxfh_priv_size;
+21 -4
net/ethtool/ioctl.c
··· 1261 1261 if (rxfh_dev.indir) 1262 1262 memcpy(rxfh_dev.indir, ethtool_rxfh_context_indir(ctx), 1263 1263 indir_bytes); 1264 - if (rxfh_dev.key) 1265 - memcpy(rxfh_dev.key, ethtool_rxfh_context_key(ctx), 1266 - user_key_size); 1267 - rxfh_dev.hfunc = ctx->hfunc; 1264 + if (!ops->rxfh_per_ctx_key) { 1265 + rxfh_dev.key_size = 0; 1266 + } else { 1267 + if (rxfh_dev.key) 1268 + memcpy(rxfh_dev.key, 1269 + ethtool_rxfh_context_key(ctx), 1270 + user_key_size); 1271 + rxfh_dev.hfunc = ctx->hfunc; 1272 + } 1268 1273 rxfh_dev.input_xfrm = ctx->input_xfrm; 1269 1274 ret = 0; 1270 1275 } else { ··· 1285 1280 offsetof(struct ethtool_rxfh, input_xfrm), 1286 1281 &rxfh_dev.input_xfrm, 1287 1282 sizeof(rxfh.input_xfrm))) { 1283 + ret = -EFAULT; 1284 + } else if (copy_to_user(useraddr + 1285 + offsetof(struct ethtool_rxfh, key_size), 1286 + &rxfh_dev.key_size, 1287 + sizeof(rxfh.key_size))) { 1288 1288 ret = -EFAULT; 1289 1289 } else if (copy_to_user(useraddr + 1290 1290 offsetof(struct ethtool_rxfh, rss_config[0]), ··· 1398 1388 return -EINVAL; 1399 1389 1400 1390 indir_bytes = dev_indir_size * sizeof(rxfh_dev.indir[0]); 1391 + 1392 + /* Check settings which may be global rather than per RSS-context */ 1393 + if (rxfh.rss_context && !ops->rxfh_per_ctx_key) 1394 + if (rxfh.key_size || 1395 + (rxfh.hfunc && rxfh.hfunc != ETH_RSS_HASH_NO_CHANGE) || 1396 + (rxfh.input_xfrm && rxfh.input_xfrm != RXH_XFRM_NO_CHANGE)) 1397 + return -EOPNOTSUPP; 1401 1398 1402 1399 rss_config = kzalloc(indir_bytes + dev_key_size, GFP_USER); 1403 1400 if (!rss_config)
+15 -6
net/ethtool/rss.c
··· 10 10 11 11 struct rss_reply_data { 12 12 struct ethnl_reply_data base; 13 + bool no_key_fields; 13 14 u32 indir_size; 14 15 u32 hkey_size; 15 16 u32 hfunc; ··· 61 60 return -EOPNOTSUPP; 62 61 63 62 /* Some drivers don't handle rss_context */ 64 - if (request->rss_context && !(ops->cap_rss_ctx_supported || 65 - ops->create_rxfh_context)) 66 - return -EOPNOTSUPP; 63 + if (request->rss_context) { 64 + if (!ops->cap_rss_ctx_supported && !ops->create_rxfh_context) 65 + return -EOPNOTSUPP; 66 + 67 + data->no_key_fields = !ops->rxfh_per_ctx_key; 68 + } 67 69 68 70 ret = ethnl_ops_begin(dev); 69 71 if (ret < 0) ··· 136 132 nla_put_u32(skb, ETHTOOL_A_RSS_CONTEXT, request->rss_context)) 137 133 return -EMSGSIZE; 138 134 135 + if ((data->indir_size && 136 + nla_put(skb, ETHTOOL_A_RSS_INDIR, 137 + sizeof(u32) * data->indir_size, data->indir_table))) 138 + return -EMSGSIZE; 139 + 140 + if (data->no_key_fields) 141 + return 0; 142 + 139 143 if ((data->hfunc && 140 144 nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc)) || 141 145 (data->input_xfrm && 142 146 nla_put_u32(skb, ETHTOOL_A_RSS_INPUT_XFRM, data->input_xfrm)) || 143 - (data->indir_size && 144 - nla_put(skb, ETHTOOL_A_RSS_INDIR, 145 - sizeof(u32) * data->indir_size, data->indir_table)) || 146 147 (data->hkey_size && 147 148 nla_put(skb, ETHTOOL_A_RSS_HKEY, data->hkey_size, data->hkey))) 148 149 return -EMSGSIZE;