* [PATCH net-next 0/2] ethtool, net/mlx4_en: RSS hash function selection
@ 2014-11-05 11:59 Amir Vadai
2014-11-05 11:59 ` [PATCH net-next 1/2] ethtool: Support for configurable RSS hash function Amir Vadai
2014-11-05 11:59 ` [PATCH net-next 2/2] net/mlx4_en: " Amir Vadai
0 siblings, 2 replies; 10+ messages in thread
From: Amir Vadai @ 2014-11-05 11:59 UTC (permalink / raw)
To: David S. Miller, Ben Hutchings
Cc: netdev, Or Gerlitz, Eyal Perry, Yevgeny Petrilin, Amir Vadai
Hi,
This patchset by Eyal adds support in set/get of RSS hash function. Current
supported functions are Toeplitz and XOR. The API is design to enable adding
new hash functions without breaking backward compatibility.
If a driver want to use this API need to implement [gs]et_rxfh_func() callbacks
in ethtool_ops.
Userspace patch will be sent after API is available in kernel.
The patchset was applied and tested over commit 30349bd ("net: phy: spi_ks8995:
remove sysfs bin file by registered attribute")
Amir
Eyal Perry (2):
ethtool: Support for configurable RSS hash function
net/mlx4_en: Support for configurable RSS hash function
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 40 +++++++++++++++++++
drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 9 +++++
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 11 ++++--
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 3 +-
include/linux/ethtool.h | 28 +++++++++++++
include/uapi/linux/ethtool.h | 6 ++-
net/core/ethtool.c | 52 +++++++++++++++++--------
7 files changed, 127 insertions(+), 22 deletions(-)
--
1.8.3.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH net-next 1/2] ethtool: Support for configurable RSS hash function
2014-11-05 11:59 [PATCH net-next 0/2] ethtool, net/mlx4_en: RSS hash function selection Amir Vadai
@ 2014-11-05 11:59 ` Amir Vadai
2014-11-05 21:51 ` Ben Hutchings
2014-11-05 11:59 ` [PATCH net-next 2/2] net/mlx4_en: " Amir Vadai
1 sibling, 1 reply; 10+ messages in thread
From: Amir Vadai @ 2014-11-05 11:59 UTC (permalink / raw)
To: David S. Miller, Ben Hutchings
Cc: netdev, Or Gerlitz, Eyal Perry, Yevgeny Petrilin, Amir Vadai
From: Eyal Perry <eyalpe@mellanox.com>
This patch adds an RSS hash functions string-set, and two
ethtool-options for set/get current RSS hash function. User-kernel API is done
through the new hfunc mask field in the ethtool_rxfh struct. A bit set
in the hfunc is corresponding to an index in the string-set.
Signed-off-by: Eyal Perry <eyalpe@mellanox.com>
Signed-off-by: Amir Vadai <amirv@mellanox.com>
---
include/linux/ethtool.h | 28 ++++++++++++++++++++++++
include/uapi/linux/ethtool.h | 6 ++++-
net/core/ethtool.c | 52 ++++++++++++++++++++++++++++++--------------
3 files changed, 69 insertions(+), 17 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index c1a2d60..61003b1 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -59,6 +59,29 @@ enum ethtool_phys_id_state {
ETHTOOL_ID_OFF
};
+enum {
+ RSS_HASH_TOP_BIT, /* Configurable RSS hash function - Toeplitz */
+ RSS_HASH_XOR_BIT, /* Configurable RSS hash function - Xor */
+
+ /*
+ * Add your fresh new hash function bits above and remember to update
+ * rss_hash_func_strings[] below
+ */
+ RSS_HASH_FUNCS_COUNT
+};
+
+#define __RSS_HASH_BIT(bit) ((u32)1 << (bit))
+#define __RSS_HASH(name) __RSS_HASH_BIT(RSS_HASH_##name##_BIT)
+
+#define RSS_HASH_TOP __RSS_HASH(TOP)
+#define RSS_HASH_XOR __RSS_HASH(XOR)
+
+static const char
+rss_hash_func_strings[RSS_HASH_FUNCS_COUNT][ETH_GSTRING_LEN] = {
+ [RSS_HASH_TOP_BIT] = "toeplitz",
+ [RSS_HASH_XOR_BIT] = "xor",
+};
+
struct net_device;
/* Some generic methods drivers may use in their ethtool_ops */
@@ -158,6 +181,9 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
* Returns zero if not supported for this specific device.
* @get_rxfh_indir_size: Get the size of the RX flow hash indirection table.
* Returns zero if not supported for this specific device.
+ * @get_rxfh_func: Get the hardware RX flow hash function.
+ * @set_rxfh_func: Set the hardware RX flow hash function. Returns a negative
+ * error code or zero.
* @get_rxfh: Get the contents of the RX flow hash indirection table and hash
* key.
* Will only be called if one or both of @get_rxfh_indir_size and
@@ -241,6 +267,8 @@ struct ethtool_ops {
int (*reset)(struct net_device *, u32 *);
u32 (*get_rxfh_key_size)(struct net_device *);
u32 (*get_rxfh_indir_size)(struct net_device *);
+ u32 (*get_rxfh_func)(struct net_device *);
+ int (*set_rxfh_func)(struct net_device *, u32);
int (*get_rxfh)(struct net_device *, u32 *indir, u8 *key);
int (*set_rxfh)(struct net_device *, const u32 *indir,
const u8 *key);
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index eb2095b..eb91da4 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -534,6 +534,7 @@ struct ethtool_pauseparam {
* @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE;
* now deprecated
* @ETH_SS_FEATURES: Device feature names
+ * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names
*/
enum ethtool_stringset {
ETH_SS_TEST = 0,
@@ -541,6 +542,7 @@ enum ethtool_stringset {
ETH_SS_PRIV_FLAGS,
ETH_SS_NTUPLE_FILTERS,
ETH_SS_FEATURES,
+ ETH_SS_RSS_HASH_FUNCS,
};
/**
@@ -900,7 +902,9 @@ struct ethtool_rxfh {
__u32 rss_context;
__u32 indir_size;
__u32 key_size;
- __u32 rsvd[2];
+ __u8 hfunc;
+ __u8 rsvd8[3];
+ __u32 rsvd32;
__u32 rss_config[0];
};
#define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 06dfb29..4791c17 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -185,6 +185,9 @@ static int __ethtool_get_sset_count(struct net_device *dev, int sset)
if (sset == ETH_SS_FEATURES)
return ARRAY_SIZE(netdev_features_strings);
+ if (sset == ETH_SS_RSS_HASH_FUNCS)
+ return ARRAY_SIZE(rss_hash_func_strings);
+
if (ops->get_sset_count && ops->get_strings)
return ops->get_sset_count(dev, sset);
else
@@ -199,6 +202,9 @@ static void __ethtool_get_strings(struct net_device *dev,
if (stringset == ETH_SS_FEATURES)
memcpy(data, netdev_features_strings,
sizeof(netdev_features_strings));
+ else if (stringset == ETH_SS_RSS_HASH_FUNCS)
+ memcpy(data, rss_hash_func_strings,
+ sizeof(rss_hash_func_strings));
else
/* ops->get_strings is valid because checked earlier */
ops->get_strings(dev, stringset, data);
@@ -682,7 +688,7 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
int ret;
const struct ethtool_ops *ops = dev->ethtool_ops;
u32 user_indir_size, user_key_size;
- u32 dev_indir_size = 0, dev_key_size = 0;
+ u32 dev_indir_size = 0, dev_key_size = 0, dev_hfunc = 0;
struct ethtool_rxfh rxfh;
u32 total_size;
u32 indir_bytes;
@@ -690,17 +696,18 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
u8 *hkey = NULL;
u8 *rss_config;
- if (!(dev->ethtool_ops->get_rxfh_indir_size ||
- dev->ethtool_ops->get_rxfh_key_size) ||
- !dev->ethtool_ops->get_rxfh)
+ if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size ||
+ ops->get_rxfh_func) || !ops->get_rxfh)
return -EOPNOTSUPP;
+ if (ops->get_rxfh_func)
+ dev_hfunc = ops->get_rxfh_func(dev);
if (ops->get_rxfh_indir_size)
dev_indir_size = ops->get_rxfh_indir_size(dev);
if (ops->get_rxfh_key_size)
dev_key_size = ops->get_rxfh_key_size(dev);
- if ((dev_key_size + dev_indir_size) == 0)
+ if ((dev_key_size + dev_indir_size + dev_hfunc) == 0)
return -EOPNOTSUPP;
if (copy_from_user(&rxfh, useraddr, sizeof(rxfh)))
@@ -709,17 +716,19 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
user_key_size = rxfh.key_size;
/* Check that reserved fields are 0 for now */
- if (rxfh.rss_context || rxfh.rsvd[0] || rxfh.rsvd[1])
+ if (rxfh.rss_context || rxfh.rsvd8[0] || rxfh.rsvd8[1] ||
+ rxfh.rsvd8[2] || rxfh.rsvd32)
return -EINVAL;
rxfh.indir_size = dev_indir_size;
rxfh.key_size = dev_key_size;
+ rxfh.hfunc = dev_hfunc;
if (copy_to_user(useraddr, &rxfh, sizeof(rxfh)))
return -EFAULT;
- /* If the user buffer size is 0, this is just a query for the
- * device table size and key size. Otherwise, if the User size is
- * not equal to device table size or key size it's an error.
+ /* If the user buffer size is 0, this is just a query for the device
+ * hash function, table size and key size. Otherwise, if the User size
+ * is not equal to device table size or key size it's an error.
*/
if (!user_indir_size && !user_key_size)
return 0;
@@ -760,32 +769,43 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
const struct ethtool_ops *ops = dev->ethtool_ops;
struct ethtool_rxnfc rx_rings;
struct ethtool_rxfh rxfh;
- u32 dev_indir_size = 0, dev_key_size = 0, i;
+ u32 dev_indir_size = 0, dev_key_size = 0, dev_hfunc = 0, i;
u32 *indir = NULL, indir_bytes = 0;
u8 *hkey = NULL;
u8 *rss_config;
u32 rss_cfg_offset = offsetof(struct ethtool_rxfh, rss_config[0]);
- if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size) ||
- !ops->get_rxnfc || !ops->set_rxfh)
+ if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size ||
+ ops->get_rxfh_func) || !ops->get_rxnfc || !ops->set_rxfh)
return -EOPNOTSUPP;
+ if (ops->get_rxfh_func)
+ dev_hfunc = ops->get_rxfh_func(dev);
if (ops->get_rxfh_indir_size)
dev_indir_size = ops->get_rxfh_indir_size(dev);
if (ops->get_rxfh_key_size)
dev_key_size = dev->ethtool_ops->get_rxfh_key_size(dev);
- if ((dev_key_size + dev_indir_size) == 0)
+ if ((dev_key_size + dev_indir_size + dev_hfunc) == 0)
return -EOPNOTSUPP;
if (copy_from_user(&rxfh, useraddr, sizeof(rxfh)))
return -EFAULT;
/* Check that reserved fields are 0 for now */
- if (rxfh.rss_context || rxfh.rsvd[0] || rxfh.rsvd[1])
+ if (rxfh.rss_context || rxfh.rsvd8[0] || rxfh.rsvd8[1] ||
+ rxfh.rsvd8[2] || rxfh.rsvd32)
return -EINVAL;
+ if (rxfh.hfunc != dev_hfunc) {
+ if (!ops->set_rxfh_func)
+ return -EOPNOTSUPP;
+ ret = ops->set_rxfh_func(dev, rxfh.hfunc);
+ if (ret)
+ return ret;
+ }
+
/* If either indir or hash key is valid, proceed further.
- * It is not valid to request that both be unchanged.
+ * Must request at least one change: indir size, hash key or function.
*/
if ((rxfh.indir_size &&
rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE &&
@@ -793,7 +813,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
(rxfh.key_size && (rxfh.key_size != dev_key_size)) ||
(rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE &&
rxfh.key_size == 0))
- return -EINVAL;
+ return rxfh.hfunc ? 0 : -EINVAL;
if (rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE)
indir_bytes = dev_indir_size * sizeof(indir[0]);
--
1.8.3.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next 2/2] net/mlx4_en: Support for configurable RSS hash function
2014-11-05 11:59 [PATCH net-next 0/2] ethtool, net/mlx4_en: RSS hash function selection Amir Vadai
2014-11-05 11:59 ` [PATCH net-next 1/2] ethtool: Support for configurable RSS hash function Amir Vadai
@ 2014-11-05 11:59 ` Amir Vadai
2014-11-05 12:27 ` Or Gerlitz
2014-11-05 13:53 ` Or Gerlitz
1 sibling, 2 replies; 10+ messages in thread
From: Amir Vadai @ 2014-11-05 11:59 UTC (permalink / raw)
To: David S. Miller, Ben Hutchings
Cc: netdev, Or Gerlitz, Eyal Perry, Yevgeny Petrilin, Amir Vadai
From: Eyal Perry <eyalpe@mellanox.com>
The ConnectX HW is capable of using one of the following hash functions:
Toeplitz and an XOR hash function.
This patch implements ethtool_ops {get,set}_rxfh_func callbacks for the
mlx4_en driver in order to query and configure the RSS hash function to
be used by the device.
Signed-off-by: Eyal Perry <eyalpe@mellanox.com>
Signed-off-by: Amir Vadai <amirv@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 40 +++++++++++++++++++++++++
drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 9 ++++++
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 11 ++++---
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 3 +-
4 files changed, 58 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 8ea4d5b..f33785a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -973,6 +973,44 @@ static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
return priv->rx_ring_num;
}
+static u32 mlx4_en_get_rxfh_func(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ return priv->rss_hash_fn;
+}
+
+static int mlx4_en_set_rxfh_func(struct net_device *dev, u32 hfunc)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ u32 prev_rss_hash_fn = priv->rss_hash_fn;
+ int err = 0;
+
+ if (!(hfunc & priv->rss_hash_fn_caps))
+ return -EINVAL;
+
+ priv->rss_hash_fn = hfunc;
+ if (hfunc == RSS_HASH_TOP && !(dev->features & NETIF_F_RXHASH))
+ en_warn(priv,
+ "Toeplitz hash function should be used in conjunction with RX hashing for optimal performance\n");
+ if (hfunc == RSS_HASH_XOR && (dev->features & NETIF_F_RXHASH))
+ en_warn(priv,
+ "Enabling both XOR Hash function and RX Hashing can limit RPS functionality\n");
+
+ mutex_lock(&mdev->state_lock);
+ if (priv->port_up && priv->rss_hash_fn != prev_rss_hash_fn) {
+ mlx4_en_stop_port(dev, 1);
+ err = mlx4_en_start_port(dev);
+ }
+ mutex_unlock(&mdev->state_lock);
+
+ if (err)
+ en_err(priv, "Failed to restart port %d\n", priv->port);
+
+ return err;
+}
+
static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -1799,6 +1837,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_rxnfc = mlx4_en_get_rxnfc,
.set_rxnfc = mlx4_en_set_rxnfc,
.get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
+ .get_rxfh_func = mlx4_en_get_rxfh_func,
+ .set_rxfh_func = mlx4_en_set_rxfh_func,
.get_rxfh = mlx4_en_get_rxfh,
.set_rxfh = mlx4_en_set_rxfh,
.get_channels = mlx4_en_get_channels,
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 0efbae9..a9e96a6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2585,6 +2585,15 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
dev->features |= NETIF_F_GSO_UDP_TUNNEL;
}
+ if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR) {
+ priv->rss_hash_fn_caps |= RSS_HASH_XOR;
+ priv->rss_hash_fn = RSS_HASH_XOR;
+ }
+ if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP) {
+ priv->rss_hash_fn_caps |= RSS_HASH_TOP;
+ priv->rss_hash_fn = RSS_HASH_TOP;
+ }
+
mdev->pndev[port] = dev;
netif_carrier_off(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index b173a0c..41c1ff9 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -1113,10 +1113,13 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
}
rss_context->flags = rss_mask;
- rss_context->hash_fn = MLX4_RSS_HASH_TOP;
- for (i = 0; i < 10; i++)
- rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
-
+ if (priv->rss_hash_fn & MLX4_RSS_HASH_XOR) {
+ rss_context->hash_fn = MLX4_RSS_HASH_XOR;
+ } else {
+ rss_context->hash_fn = MLX4_RSS_HASH_TOP;
+ for (i = 0; i < 10; i++)
+ rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
+ }
err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
&rss_map->indir_qp, &rss_map->indir_state);
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index ef83d12..e1c3364 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -375,7 +375,6 @@ struct mlx4_en_port_profile {
};
struct mlx4_en_profile {
- int rss_xor;
int udp_rss;
u8 rss_mask;
u32 active_ports;
@@ -615,6 +614,8 @@ struct mlx4_en_priv {
__be16 vxlan_port;
u32 pflags;
+ u8 rss_hash_fn;
+ u8 rss_hash_fn_caps;
};
enum mlx4_en_wol {
--
1.8.3.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH net-next 2/2] net/mlx4_en: Support for configurable RSS hash function
2014-11-05 11:59 ` [PATCH net-next 2/2] net/mlx4_en: " Amir Vadai
@ 2014-11-05 12:27 ` Or Gerlitz
2014-11-05 13:05 ` Eyal perry
2014-11-05 13:53 ` Or Gerlitz
1 sibling, 1 reply; 10+ messages in thread
From: Or Gerlitz @ 2014-11-05 12:27 UTC (permalink / raw)
To: Eyal Perry
Cc: Amir Vadai, David S. Miller, Ben Hutchings, netdev,
Yevgeny Petrilin
On 11/5/2014 1:59 PM, Amir Vadai wrote:
> From: Eyal Perry <eyalpe@mellanox.com>
>
> The ConnectX HW is capable of using one of the following hash functions:
> Toeplitz and an XOR hash function.
> This patch implements ethtool_ops {get,set}_rxfh_func callbacks for the
> mlx4_en driver in order to query and configure the RSS hash function to
> be used by the device.
>
> Signed-off-by: Eyal Perry <eyalpe@mellanox.com>
> Signed-off-by: Amir Vadai <amirv@mellanox.com>
> ---
> drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 40 +++++++++++++++++++++++++
> drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 9 ++++++
> drivers/net/ethernet/mellanox/mlx4/en_rx.c | 11 ++++---
> drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 3 +-
> 4 files changed, 58 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
> index 8ea4d5b..f33785a 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
> @@ -973,6 +973,44 @@ static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
> return priv->rx_ring_num;
> }
>
> +static u32 mlx4_en_get_rxfh_func(struct net_device *dev)
> +{
> + struct mlx4_en_priv *priv = netdev_priv(dev);
> +
> + return priv->rss_hash_fn;
> +}
> +
> +static int mlx4_en_set_rxfh_func(struct net_device *dev, u32 hfunc)
> +{
> + struct mlx4_en_priv *priv = netdev_priv(dev);
> + struct mlx4_en_dev *mdev = priv->mdev;
> + u32 prev_rss_hash_fn = priv->rss_hash_fn;
> + int err = 0;
> +
> + if (!(hfunc & priv->rss_hash_fn_caps))
> + return -EINVAL;
> +
> + priv->rss_hash_fn = hfunc;
Seems that you are blindly setting here priv->rss_hash_fn to the
function (xor or top) requested
by the user w.o prior checking if the firmware actually supports that
(e.g test it against priv->rss_hash_fn_caps, right?
> + if (hfunc == RSS_HASH_TOP && !(dev->features & NETIF_F_RXHASH))
> + en_warn(priv,
> + "Toeplitz hash function should be used in conjunction with RX hashing for optimal performance\n");
> + if (hfunc == RSS_HASH_XOR && (dev->features & NETIF_F_RXHASH))
> + en_warn(priv,
> + "Enabling both XOR Hash function and RX Hashing can limit RPS functionality\n");
> +
> + mutex_lock(&mdev->state_lock);
> + if (priv->port_up && priv->rss_hash_fn != prev_rss_hash_fn) {
> + mlx4_en_stop_port(dev, 1);
> + err = mlx4_en_start_port(dev);
> + }
> + mutex_unlock(&mdev->state_lock);
> +
> + if (err)
> + en_err(priv, "Failed to restart port %d\n", priv->port);
> +
> + return err;
> +}
> +
> static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key)
> {
> struct mlx4_en_priv *priv = netdev_priv(dev);
> @@ -1799,6 +1837,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
> .get_rxnfc = mlx4_en_get_rxnfc,
> .set_rxnfc = mlx4_en_set_rxnfc,
> .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
> + .get_rxfh_func = mlx4_en_get_rxfh_func,
> + .set_rxfh_func = mlx4_en_set_rxfh_func,
> .get_rxfh = mlx4_en_get_rxfh,
> .set_rxfh = mlx4_en_set_rxfh,
> .get_channels = mlx4_en_get_channels,
> diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> index 0efbae9..a9e96a6 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> @@ -2585,6 +2585,15 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
> dev->features |= NETIF_F_GSO_UDP_TUNNEL;
> }
>
> + if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR) {
> + priv->rss_hash_fn_caps |= RSS_HASH_XOR;
> + priv->rss_hash_fn = RSS_HASH_XOR;
> + }
> + if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP) {
> + priv->rss_hash_fn_caps |= RSS_HASH_TOP;
> + priv->rss_hash_fn = RSS_HASH_TOP;
> + }
> +
> mdev->pndev[port] = dev;
>
> netif_carrier_off(dev);
> diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
> index b173a0c..41c1ff9 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
> @@ -1113,10 +1113,13 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
> }
>
> rss_context->flags = rss_mask;
> - rss_context->hash_fn = MLX4_RSS_HASH_TOP;
> - for (i = 0; i < 10; i++)
> - rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
> -
> + if (priv->rss_hash_fn & MLX4_RSS_HASH_XOR) {
> + rss_context->hash_fn = MLX4_RSS_HASH_XOR;
> + } else {
> + rss_context->hash_fn = MLX4_RSS_HASH_TOP;
> + for (i = 0; i < 10; i++)
> + rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
> + }
So this patch effectively changes the default from top to xor, right? is
that intentional? if yes, spare few words on the change log.
> err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
> &rss_map->indir_qp, &rss_map->indir_state);
> if (err)
> diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
> index ef83d12..e1c3364 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
> +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
> @@ -375,7 +375,6 @@ struct mlx4_en_port_profile {
> };
>
> struct mlx4_en_profile {
> - int rss_xor;
> int udp_rss;
> u8 rss_mask;
> u32 active_ports;
> @@ -615,6 +614,8 @@ struct mlx4_en_priv {
> __be16 vxlan_port;
>
> u32 pflags;
> + u8 rss_hash_fn;
> + u8 rss_hash_fn_caps;
> };
>
> enum mlx4_en_wol {
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next 2/2] net/mlx4_en: Support for configurable RSS hash function
2014-11-05 12:27 ` Or Gerlitz
@ 2014-11-05 13:05 ` Eyal perry
2014-11-05 13:30 ` Or Gerlitz
0 siblings, 1 reply; 10+ messages in thread
From: Eyal perry @ 2014-11-05 13:05 UTC (permalink / raw)
To: Or Gerlitz, Eyal Perry
Cc: Amir Vadai, David S. Miller, Ben Hutchings, netdev,
Yevgeny Petrilin
On 11/5/2014 2:27 PM, Or Gerlitz wrote:
> On 11/5/2014 1:59 PM, Amir Vadai wrote:
>> From: Eyal Perry <eyalpe@mellanox.com>
>>
>> The ConnectX HW is capable of using one of the following hash functions:
>> Toeplitz and an XOR hash function.
>> This patch implements ethtool_ops {get,set}_rxfh_func callbacks for the
>> mlx4_en driver in order to query and configure the RSS hash function to
>> be used by the device.
>>
>> Signed-off-by: Eyal Perry <eyalpe@mellanox.com>
>> Signed-off-by: Amir Vadai <amirv@mellanox.com>
>> ---
>> drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 40
>> +++++++++++++++++++++++++
>> drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 9 ++++++
>> drivers/net/ethernet/mellanox/mlx4/en_rx.c | 11 ++++---
>> drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 3 +-
>> 4 files changed, 58 insertions(+), 5 deletions(-)
>>
[...]
>> +
>> +static int mlx4_en_set_rxfh_func(struct net_device *dev, u32 hfunc)
>> +{
>> + struct mlx4_en_priv *priv = netdev_priv(dev);
>> + struct mlx4_en_dev *mdev = priv->mdev;
>> + u32 prev_rss_hash_fn = priv->rss_hash_fn;
>> + int err = 0;
>> +
>> + if (!(hfunc & priv->rss_hash_fn_caps))
>> + return -EINVAL;
>> +
>> + priv->rss_hash_fn = hfunc;
>
> Seems that you are blindly setting here priv->rss_hash_fn to the
> function (xor or top) requested
> by the user w.o prior checking if the firmware actually supports that
> (e.g test it against priv->rss_hash_fn_caps, right?
>
That exactly what I do 3 lines above, priv->rss_hash_fn_caps is derived
from firmware capabilities.
[...]
>> --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
>> +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
>> @@ -1113,10 +1113,13 @@ int mlx4_en_config_rss_steer(struct
>> mlx4_en_priv *priv)
>> }
>> rss_context->flags = rss_mask;
>> - rss_context->hash_fn = MLX4_RSS_HASH_TOP;
>> - for (i = 0; i < 10; i++)
>> - rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
>> -
>> + if (priv->rss_hash_fn & MLX4_RSS_HASH_XOR) {
>> + rss_context->hash_fn = MLX4_RSS_HASH_XOR;
>> + } else {
>> + rss_context->hash_fn = MLX4_RSS_HASH_TOP;
>> + for (i = 0; i < 10; i++)
>> + rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
>> + }
>
> So this patch effectively changes the default from top to xor, right? is
> that intentional? if yes, spare few words on the change log.
>
No, in general the default shouldn't be affected by the patch (unless
there's a bug). The default value is set in mlx4_en_init_netdev() and it
will remain Toeplitz unless firmware is supports only XOR hash function.
[...]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next 2/2] net/mlx4_en: Support for configurable RSS hash function
2014-11-05 13:05 ` Eyal perry
@ 2014-11-05 13:30 ` Or Gerlitz
2014-11-05 13:48 ` Eyal perry
0 siblings, 1 reply; 10+ messages in thread
From: Or Gerlitz @ 2014-11-05 13:30 UTC (permalink / raw)
To: Eyal perry, Eyal Perry
Cc: Amir Vadai, David S. Miller, Ben Hutchings, netdev,
Yevgeny Petrilin
On 11/5/2014 3:05 PM, Eyal perry wrote:
> On 11/5/2014 2:27 PM, Or Gerlitz wrote:
>>> +
>>> +static int mlx4_en_set_rxfh_func(struct net_device *dev, u32 hfunc)
>>> +{
>>> + struct mlx4_en_priv *priv = netdev_priv(dev);
>>> + struct mlx4_en_dev *mdev = priv->mdev;
>>> + u32 prev_rss_hash_fn = priv->rss_hash_fn;
>>> + int err = 0;
>>> +
>>> + if (!(hfunc & priv->rss_hash_fn_caps))
>>> + return -EINVAL;
>>> +
>>> + priv->rss_hash_fn = hfunc;
>> Seems that you are blindly setting here priv->rss_hash_fn to the function (xor or top) requested by the user w.o prior checking if the firmware actually supports that
>> (e.g test it against priv->rss_hash_fn_caps, right?
>>
> That exactly what I do 3 lines above, priv->rss_hash_fn_caps is derived from firmware capabilities.
got it, thanks.
>
> [...]
>
>>> --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
>>> +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
>>> @@ -1113,10 +1113,13 @@ int mlx4_en_config_rss_steer(struct
>>> mlx4_en_priv *priv)
>>> }
>>> rss_context->flags = rss_mask;
>>> - rss_context->hash_fn = MLX4_RSS_HASH_TOP;
>>> - for (i = 0; i < 10; i++)
>>> - rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
>>> -
>>> + if (priv->rss_hash_fn & MLX4_RSS_HASH_XOR) {
>>> + rss_context->hash_fn = MLX4_RSS_HASH_XOR;
>>> + } else {
>>> + rss_context->hash_fn = MLX4_RSS_HASH_TOP;
>>> + for (i = 0; i < 10; i++)
>>> + rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
>>> + }
>> So this patch effectively changes the default from top to xor, right? is
>> that intentional? if yes, spare few words on the change log.
>>
> No, in general the default shouldn't be affected by the patch (unless
> there's a bug). The default value is set in mlx4_en_init_netdev() and it
> will remain Toeplitz unless firmware is supports only XOR hash function.
>
Oh, I see why I was confused and what I think need to be fixed. You are
using both MLX4_RSS_HASH_TOP/XOR and RSS_HASH_TOP/XOR, any reason for that?
Also, priv->rss_hash_fn should equal one value, right? so this code "if
(priv->rss_hash_fn & something)" is confusing, should be "if
(priv->rss_hash_fn == something)"
Or.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next 2/2] net/mlx4_en: Support for configurable RSS hash function
2014-11-05 13:30 ` Or Gerlitz
@ 2014-11-05 13:48 ` Eyal perry
0 siblings, 0 replies; 10+ messages in thread
From: Eyal perry @ 2014-11-05 13:48 UTC (permalink / raw)
To: Or Gerlitz, Eyal Perry
Cc: Amir Vadai, David S. Miller, Ben Hutchings, netdev,
Yevgeny Petrilin
On 11/5/2014 3:30 PM, Or Gerlitz wrote:
> On 11/5/2014 3:05 PM, Eyal perry wrote:
>> On 11/5/2014 2:27 PM, Or Gerlitz wrote:
>>>> +
>>>> +static int mlx4_en_set_rxfh_func(struct net_device *dev, u32 hfunc)
>>>> +{
>>>> + struct mlx4_en_priv *priv = netdev_priv(dev);
>>>> + struct mlx4_en_dev *mdev = priv->mdev;
>>>> + u32 prev_rss_hash_fn = priv->rss_hash_fn;
>>>> + int err = 0;
>>>> +
>>>> + if (!(hfunc & priv->rss_hash_fn_caps))
>>>> + return -EINVAL;
>>>> +
>>>> + priv->rss_hash_fn = hfunc;
>>> Seems that you are blindly setting here priv->rss_hash_fn to the
>>> function (xor or top) requested by the user w.o prior checking if the
>>> firmware actually supports that
>>> (e.g test it against priv->rss_hash_fn_caps, right?
>>>
>> That exactly what I do 3 lines above, priv->rss_hash_fn_caps is
>> derived from firmware capabilities.
>
> got it, thanks.
>
>>
>> [...]
>>
>>>> --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
>>>> +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
>>>> @@ -1113,10 +1113,13 @@ int mlx4_en_config_rss_steer(struct
>>>> mlx4_en_priv *priv)
>>>> }
>>>> rss_context->flags = rss_mask;
>>>> - rss_context->hash_fn = MLX4_RSS_HASH_TOP;
>>>> - for (i = 0; i < 10; i++)
>>>> - rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
>>>> -
>>>> + if (priv->rss_hash_fn & MLX4_RSS_HASH_XOR) {
>>>> + rss_context->hash_fn = MLX4_RSS_HASH_XOR;
>>>> + } else {
>>>> + rss_context->hash_fn = MLX4_RSS_HASH_TOP;
>>>> + for (i = 0; i < 10; i++)
>>>> + rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
>>>> + }
>>> So this patch effectively changes the default from top to xor, right? is
>>> that intentional? if yes, spare few words on the change log.
>>>
>> No, in general the default shouldn't be affected by the patch (unless
>> there's a bug). The default value is set in mlx4_en_init_netdev() and it
>> will remain Toeplitz unless firmware is supports only XOR hash function.
>>
>
> Oh, I see why I was confused and what I think need to be fixed. You are
> using both MLX4_RSS_HASH_TOP/XOR and RSS_HASH_TOP/XOR, any reason for that?
Yes, RSS_HASH_TOP/XOR are bits on a generic bitmask while the
MLX4_RSS_HASH_TOP/XOR are HW specific values.
>
> Also, priv->rss_hash_fn should equal one value, right? so this code "if
> (priv->rss_hash_fn & something)" is confusing, should be "if
> (priv->rss_hash_fn == something)"
That's right, I'll fix it for V1.
Thanks.
>
> Or.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next 2/2] net/mlx4_en: Support for configurable RSS hash function
2014-11-05 11:59 ` [PATCH net-next 2/2] net/mlx4_en: " Amir Vadai
2014-11-05 12:27 ` Or Gerlitz
@ 2014-11-05 13:53 ` Or Gerlitz
1 sibling, 0 replies; 10+ messages in thread
From: Or Gerlitz @ 2014-11-05 13:53 UTC (permalink / raw)
To: Eyal Perry
Cc: Amir Vadai, David S. Miller, Ben Hutchings, netdev,
Yevgeny Petrilin
On 11/5/2014 1:59 PM, Amir Vadai wrote:
> --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> @@ -2585,6 +2585,15 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
> dev->features |= NETIF_F_GSO_UDP_TUNNEL;
> }
>
> + if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR) {
> + priv->rss_hash_fn_caps |= RSS_HASH_XOR;
> + priv->rss_hash_fn = RSS_HASH_XOR;
> + }
> + if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP) {
> + priv->rss_hash_fn_caps |= RSS_HASH_TOP;
> + priv->rss_hash_fn = RSS_HASH_TOP;
> + }
> +
can we somehow change this code to be more clear and assign
priv->rss_hash_fn once?
> mdev->pndev[port] = dev;
>
> netif_carrier_off(dev);
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next 1/2] ethtool: Support for configurable RSS hash function
2014-11-05 11:59 ` [PATCH net-next 1/2] ethtool: Support for configurable RSS hash function Amir Vadai
@ 2014-11-05 21:51 ` Ben Hutchings
2014-11-06 9:41 ` Eyal perry
0 siblings, 1 reply; 10+ messages in thread
From: Ben Hutchings @ 2014-11-05 21:51 UTC (permalink / raw)
To: Amir Vadai
Cc: David S. Miller, netdev, Or Gerlitz, Eyal Perry, Yevgeny Petrilin
[-- Attachment #1: Type: text/plain, Size: 7383 bytes --]
On Wed, 2014-11-05 at 13:59 +0200, Amir Vadai wrote:
> From: Eyal Perry <eyalpe@mellanox.com>
>
> This patch adds an RSS hash functions string-set, and two
> ethtool-options for set/get current RSS hash function. User-kernel API is done
> through the new hfunc mask field in the ethtool_rxfh struct. A bit set
> in the hfunc is corresponding to an index in the string-set.
>
> Signed-off-by: Eyal Perry <eyalpe@mellanox.com>
> Signed-off-by: Amir Vadai <amirv@mellanox.com>
> ---
> include/linux/ethtool.h | 28 ++++++++++++++++++++++++
> include/uapi/linux/ethtool.h | 6 ++++-
> net/core/ethtool.c | 52 ++++++++++++++++++++++++++++++--------------
> 3 files changed, 69 insertions(+), 17 deletions(-)
>
> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
> index c1a2d60..61003b1 100644
> --- a/include/linux/ethtool.h
> +++ b/include/linux/ethtool.h
> @@ -59,6 +59,29 @@ enum ethtool_phys_id_state {
> ETHTOOL_ID_OFF
> };
>
> +enum {
> + RSS_HASH_TOP_BIT, /* Configurable RSS hash function - Toeplitz */
> + RSS_HASH_XOR_BIT, /* Configurable RSS hash function - Xor */
> +
> + /*
> + * Add your fresh new hash function bits above and remember to update
> + * rss_hash_func_strings[] below
> + */
> + RSS_HASH_FUNCS_COUNT
> +};
> +
> +#define __RSS_HASH_BIT(bit) ((u32)1 << (bit))
> +#define __RSS_HASH(name) __RSS_HASH_BIT(RSS_HASH_##name##_BIT)
> +
> +#define RSS_HASH_TOP __RSS_HASH(TOP)
> +#define RSS_HASH_XOR __RSS_HASH(XOR)
I think #define RSS_HASH_UNKNOWN 0 might also be useful.
And I think all of these names should get an ETH_ prefix.
> +static const char
> +rss_hash_func_strings[RSS_HASH_FUNCS_COUNT][ETH_GSTRING_LEN] = {
> + [RSS_HASH_TOP_BIT] = "toeplitz",
> + [RSS_HASH_XOR_BIT] = "xor",
> +};
This belongs in net/core/ethtool.c.
> struct net_device;
>
> /* Some generic methods drivers may use in their ethtool_ops */
> @@ -158,6 +181,9 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
> * Returns zero if not supported for this specific device.
> * @get_rxfh_indir_size: Get the size of the RX flow hash indirection table.
> * Returns zero if not supported for this specific device.
> + * @get_rxfh_func: Get the hardware RX flow hash function.
> + * @set_rxfh_func: Set the hardware RX flow hash function. Returns a negative
> + * error code or zero.
> * @get_rxfh: Get the contents of the RX flow hash indirection table and hash
> * key.
> * Will only be called if one or both of @get_rxfh_indir_size and
> @@ -241,6 +267,8 @@ struct ethtool_ops {
> int (*reset)(struct net_device *, u32 *);
> u32 (*get_rxfh_key_size)(struct net_device *);
> u32 (*get_rxfh_indir_size)(struct net_device *);
> + u32 (*get_rxfh_func)(struct net_device *);
> + int (*set_rxfh_func)(struct net_device *, u32);
Why not another parameter to get_rxfh/set_rxfh? I know it's a pain to
update all the implementations, but changing algorithm potentially
changes the supported indirection table and key lengths. They have to
be validated together.
> int (*get_rxfh)(struct net_device *, u32 *indir, u8 *key);
> int (*set_rxfh)(struct net_device *, const u32 *indir,
> const u8 *key);
> diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
> index eb2095b..eb91da4 100644
> --- a/include/uapi/linux/ethtool.h
> +++ b/include/uapi/linux/ethtool.h
> @@ -534,6 +534,7 @@ struct ethtool_pauseparam {
> * @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE;
> * now deprecated
> * @ETH_SS_FEATURES: Device feature names
> + * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names
> */
> enum ethtool_stringset {
> ETH_SS_TEST = 0,
> @@ -541,6 +542,7 @@ enum ethtool_stringset {
> ETH_SS_PRIV_FLAGS,
> ETH_SS_NTUPLE_FILTERS,
> ETH_SS_FEATURES,
> + ETH_SS_RSS_HASH_FUNCS,
> };
>
> /**
> @@ -900,7 +902,9 @@ struct ethtool_rxfh {
> __u32 rss_context;
> __u32 indir_size;
> __u32 key_size;
> - __u32 rsvd[2];
> + __u8 hfunc;
Missing kernel-doc. This needs to be very clear about what the valid
values are.
> + __u8 rsvd8[3];
> + __u32 rsvd32;
> __u32 rss_config[0];
> };
> #define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff
> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> index 06dfb29..4791c17 100644
> --- a/net/core/ethtool.c
> +++ b/net/core/ethtool.c
> @@ -185,6 +185,9 @@ static int __ethtool_get_sset_count(struct net_device *dev, int sset)
> if (sset == ETH_SS_FEATURES)
> return ARRAY_SIZE(netdev_features_strings);
>
> + if (sset == ETH_SS_RSS_HASH_FUNCS)
> + return ARRAY_SIZE(rss_hash_func_strings);
> +
> if (ops->get_sset_count && ops->get_strings)
> return ops->get_sset_count(dev, sset);
> else
[...]
> @@ -760,32 +769,43 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
> const struct ethtool_ops *ops = dev->ethtool_ops;
> struct ethtool_rxnfc rx_rings;
> struct ethtool_rxfh rxfh;
> - u32 dev_indir_size = 0, dev_key_size = 0, i;
> + u32 dev_indir_size = 0, dev_key_size = 0, dev_hfunc = 0, i;
> u32 *indir = NULL, indir_bytes = 0;
> u8 *hkey = NULL;
> u8 *rss_config;
> u32 rss_cfg_offset = offsetof(struct ethtool_rxfh, rss_config[0]);
>
> - if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size) ||
> - !ops->get_rxnfc || !ops->set_rxfh)
> + if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size ||
> + ops->get_rxfh_func) || !ops->get_rxnfc || !ops->set_rxfh)
> return -EOPNOTSUPP;
>
> + if (ops->get_rxfh_func)
> + dev_hfunc = ops->get_rxfh_func(dev);
> if (ops->get_rxfh_indir_size)
> dev_indir_size = ops->get_rxfh_indir_size(dev);
> if (ops->get_rxfh_key_size)
> dev_key_size = dev->ethtool_ops->get_rxfh_key_size(dev);
> - if ((dev_key_size + dev_indir_size) == 0)
> + if ((dev_key_size + dev_indir_size + dev_hfunc) == 0)
> return -EOPNOTSUPP;
>
> if (copy_from_user(&rxfh, useraddr, sizeof(rxfh)))
> return -EFAULT;
>
> /* Check that reserved fields are 0 for now */
> - if (rxfh.rss_context || rxfh.rsvd[0] || rxfh.rsvd[1])
> + if (rxfh.rss_context || rxfh.rsvd8[0] || rxfh.rsvd8[1] ||
> + rxfh.rsvd8[2] || rxfh.rsvd32)
> return -EINVAL;
>
> + if (rxfh.hfunc != dev_hfunc) {
> + if (!ops->set_rxfh_func)
> + return -EOPNOTSUPP;
> + ret = ops->set_rxfh_func(dev, rxfh.hfunc);
> + if (ret)
> + return ret;
> + }
> +
> /* If either indir or hash key is valid, proceed further.
> - * It is not valid to request that both be unchanged.
> + * Must request at least one change: indir size, hash key or function.
> */
> if ((rxfh.indir_size &&
> rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE &&
> @@ -793,7 +813,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
> (rxfh.key_size && (rxfh.key_size != dev_key_size)) ||
> (rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE &&
> rxfh.key_size == 0))
> - return -EINVAL;
> + return rxfh.hfunc ? 0 : -EINVAL;
Shouldn't the condition be rxfh.hfunc != dev_hfunc ?
Ben.
> if (rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE)
> indir_bytes = dev_indir_size * sizeof(indir[0]);
--
Ben Hutchings
The program is absolutely right; therefore, the computer must be wrong.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 811 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next 1/2] ethtool: Support for configurable RSS hash function
2014-11-05 21:51 ` Ben Hutchings
@ 2014-11-06 9:41 ` Eyal perry
0 siblings, 0 replies; 10+ messages in thread
From: Eyal perry @ 2014-11-06 9:41 UTC (permalink / raw)
To: Ben Hutchings, Amir Vadai
Cc: David S. Miller, netdev, Or Gerlitz, Eyal Perry, Yevgeny Petrilin
On 11/5/2014 11:51 PM, Ben Hutchings wrote:
> On Wed, 2014-11-05 at 13:59 +0200, Amir Vadai wrote:
>> From: Eyal Perry <eyalpe@mellanox.com>
>>
>> This patch adds an RSS hash functions string-set, and two
>> ethtool-options for set/get current RSS hash function. User-kernel API is done
>> through the new hfunc mask field in the ethtool_rxfh struct. A bit set
>> in the hfunc is corresponding to an index in the string-set.
>>
>> Signed-off-by: Eyal Perry <eyalpe@mellanox.com>
>> Signed-off-by: Amir Vadai <amirv@mellanox.com>
>> ---
>> include/linux/ethtool.h | 28 ++++++++++++++++++++++++
>> include/uapi/linux/ethtool.h | 6 ++++-
>> net/core/ethtool.c | 52 ++++++++++++++++++++++++++++++--------------
>> 3 files changed, 69 insertions(+), 17 deletions(-)
>>
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index c1a2d60..61003b1 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -59,6 +59,29 @@ enum ethtool_phys_id_state {
>> ETHTOOL_ID_OFF
>> };
>>
>> +enum {
>> + RSS_HASH_TOP_BIT, /* Configurable RSS hash function - Toeplitz */
>> + RSS_HASH_XOR_BIT, /* Configurable RSS hash function - Xor */
>> +
>> + /*
>> + * Add your fresh new hash function bits above and remember to update
>> + * rss_hash_func_strings[] below
>> + */
>> + RSS_HASH_FUNCS_COUNT
>> +};
>> +
>> +#define __RSS_HASH_BIT(bit) ((u32)1 << (bit))
>> +#define __RSS_HASH(name) __RSS_HASH_BIT(RSS_HASH_##name##_BIT)
>> +
>> +#define RSS_HASH_TOP __RSS_HASH(TOP)
>> +#define RSS_HASH_XOR __RSS_HASH(XOR)
>
> I think #define RSS_HASH_UNKNOWN 0 might also be useful.
>
> And I think all of these names should get an ETH_ prefix.
>
I'll add it in V1.
>> +static const char
>> +rss_hash_func_strings[RSS_HASH_FUNCS_COUNT][ETH_GSTRING_LEN] = {
>> + [RSS_HASH_TOP_BIT] = "toeplitz",
>> + [RSS_HASH_XOR_BIT] = "xor",
>> +};
>
> This belongs in net/core/ethtool.c.
>
I agree, will be fixed in V1.
>> struct net_device;
>>
>> /* Some generic methods drivers may use in their ethtool_ops */
>> @@ -158,6 +181,9 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
>> * Returns zero if not supported for this specific device.
>> * @get_rxfh_indir_size: Get the size of the RX flow hash indirection table.
>> * Returns zero if not supported for this specific device.
>> + * @get_rxfh_func: Get the hardware RX flow hash function.
>> + * @set_rxfh_func: Set the hardware RX flow hash function. Returns a negative
>> + * error code or zero.
>> * @get_rxfh: Get the contents of the RX flow hash indirection table and hash
>> * key.
>> * Will only be called if one or both of @get_rxfh_indir_size and
>> @@ -241,6 +267,8 @@ struct ethtool_ops {
>> int (*reset)(struct net_device *, u32 *);
>> u32 (*get_rxfh_key_size)(struct net_device *);
>> u32 (*get_rxfh_indir_size)(struct net_device *);
>> + u32 (*get_rxfh_func)(struct net_device *);
>> + int (*set_rxfh_func)(struct net_device *, u32);
>
> Why not another parameter to get_rxfh/set_rxfh? I know it's a pain to
> update all the implementations, but changing algorithm potentially
> changes the supported indirection table and key lengths. They have to
> be validated together.
>
OK, I'll do it for V1.
>> int (*get_rxfh)(struct net_device *, u32 *indir, u8 *key);
>> int (*set_rxfh)(struct net_device *, const u32 *indir,
>> const u8 *key);
>> diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
>> index eb2095b..eb91da4 100644
>> --- a/include/uapi/linux/ethtool.h
>> +++ b/include/uapi/linux/ethtool.h
>> @@ -534,6 +534,7 @@ struct ethtool_pauseparam {
>> * @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE;
>> * now deprecated
>> * @ETH_SS_FEATURES: Device feature names
>> + * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names
>> */
>> enum ethtool_stringset {
>> ETH_SS_TEST = 0,
>> @@ -541,6 +542,7 @@ enum ethtool_stringset {
>> ETH_SS_PRIV_FLAGS,
>> ETH_SS_NTUPLE_FILTERS,
>> ETH_SS_FEATURES,
>> + ETH_SS_RSS_HASH_FUNCS,
>> };
>>
>> /**
>> @@ -900,7 +902,9 @@ struct ethtool_rxfh {
>> __u32 rss_context;
>> __u32 indir_size;
>> __u32 key_size;
>> - __u32 rsvd[2];
>> + __u8 hfunc;
>
> Missing kernel-doc. This needs to be very clear about what the valid
> values are.
>
I'll add it in V1.
>> + __u8 rsvd8[3];
>> + __u32 rsvd32;
>> __u32 rss_config[0];
>> };
>> #define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff
>> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
>> index 06dfb29..4791c17 100644
>> --- a/net/core/ethtool.c
>> +++ b/net/core/ethtool.c
>> @@ -185,6 +185,9 @@ static int __ethtool_get_sset_count(struct net_device *dev, int sset)
>> if (sset == ETH_SS_FEATURES)
>> return ARRAY_SIZE(netdev_features_strings);
>>
>> + if (sset == ETH_SS_RSS_HASH_FUNCS)
>> + return ARRAY_SIZE(rss_hash_func_strings);
>> +
>> if (ops->get_sset_count && ops->get_strings)
>> return ops->get_sset_count(dev, sset);
>> else
> [...]
>> @@ -760,32 +769,43 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
>> const struct ethtool_ops *ops = dev->ethtool_ops;
>> struct ethtool_rxnfc rx_rings;
>> struct ethtool_rxfh rxfh;
>> - u32 dev_indir_size = 0, dev_key_size = 0, i;
>> + u32 dev_indir_size = 0, dev_key_size = 0, dev_hfunc = 0, i;
>> u32 *indir = NULL, indir_bytes = 0;
>> u8 *hkey = NULL;
>> u8 *rss_config;
>> u32 rss_cfg_offset = offsetof(struct ethtool_rxfh, rss_config[0]);
>>
>> - if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size) ||
>> - !ops->get_rxnfc || !ops->set_rxfh)
>> + if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size ||
>> + ops->get_rxfh_func) || !ops->get_rxnfc || !ops->set_rxfh)
>> return -EOPNOTSUPP;
>>
>> + if (ops->get_rxfh_func)
>> + dev_hfunc = ops->get_rxfh_func(dev);
>> if (ops->get_rxfh_indir_size)
>> dev_indir_size = ops->get_rxfh_indir_size(dev);
>> if (ops->get_rxfh_key_size)
>> dev_key_size = dev->ethtool_ops->get_rxfh_key_size(dev);
>> - if ((dev_key_size + dev_indir_size) == 0)
>> + if ((dev_key_size + dev_indir_size + dev_hfunc) == 0)
>> return -EOPNOTSUPP;
>>
>> if (copy_from_user(&rxfh, useraddr, sizeof(rxfh)))
>> return -EFAULT;
>>
>> /* Check that reserved fields are 0 for now */
>> - if (rxfh.rss_context || rxfh.rsvd[0] || rxfh.rsvd[1])
>> + if (rxfh.rss_context || rxfh.rsvd8[0] || rxfh.rsvd8[1] ||
>> + rxfh.rsvd8[2] || rxfh.rsvd32)
>> return -EINVAL;
>>
>> + if (rxfh.hfunc != dev_hfunc) {
>> + if (!ops->set_rxfh_func)
>> + return -EOPNOTSUPP;
>> + ret = ops->set_rxfh_func(dev, rxfh.hfunc);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> /* If either indir or hash key is valid, proceed further.
>> - * It is not valid to request that both be unchanged.
>> + * Must request at least one change: indir size, hash key or function.
>> */
>> if ((rxfh.indir_size &&
>> rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE &&
>> @@ -793,7 +813,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
>> (rxfh.key_size && (rxfh.key_size != dev_key_size)) ||
>> (rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE &&
>> rxfh.key_size == 0))
>> - return -EINVAL;
>> + return rxfh.hfunc ? 0 : -EINVAL;
>
> Shouldn't the condition be rxfh.hfunc != dev_hfunc ?
>
> Ben.
>
On current implementation it's not necessary since we have already
checked that above. However, according to your suggestion, after I'll
remove the set/get_rxfh_func() callbacks I wouldn't be able to check
that condition at this point of the code.
Best Regards,
Eyal.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2014-11-06 9:41 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-05 11:59 [PATCH net-next 0/2] ethtool, net/mlx4_en: RSS hash function selection Amir Vadai
2014-11-05 11:59 ` [PATCH net-next 1/2] ethtool: Support for configurable RSS hash function Amir Vadai
2014-11-05 21:51 ` Ben Hutchings
2014-11-06 9:41 ` Eyal perry
2014-11-05 11:59 ` [PATCH net-next 2/2] net/mlx4_en: " Amir Vadai
2014-11-05 12:27 ` Or Gerlitz
2014-11-05 13:05 ` Eyal perry
2014-11-05 13:30 ` Or Gerlitz
2014-11-05 13:48 ` Eyal perry
2014-11-05 13:53 ` Or Gerlitz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).