Commit 45bf454a authored by Maor Gottlieb's avatar Maor Gottlieb Committed by David S. Miller

net/mlx5e: Enabling aRFS mechanism

Accelerated RFS requires that ntuple filtering is enabled via
ethtool and driver supports ndo_rx_flow_steer.
When the ntuple filtering is enabled, we modify the l3_l4 ttc
rules to point on the aRFS flow tables and when the filtering
is disabled, we modify the l3_l4 ttc rules to point on the RSS
TIRs.
Signed-off-by: default avatarMaor Gottlieb <maorg@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 18c908e4
...@@ -690,9 +690,21 @@ static inline int mlx5e_arfs_create_tables(struct mlx5e_priv *priv) ...@@ -690,9 +690,21 @@ static inline int mlx5e_arfs_create_tables(struct mlx5e_priv *priv)
} }
static inline void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv) {} static inline void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv) {}
static inline int mlx5e_arfs_enable(struct mlx5e_priv *priv)
{
return -ENOTSUPP;
}
static inline int mlx5e_arfs_disable(struct mlx5e_priv *priv)
{
return -ENOTSUPP;
}
#else #else
int mlx5e_arfs_create_tables(struct mlx5e_priv *priv); int mlx5e_arfs_create_tables(struct mlx5e_priv *priv);
void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv); void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv);
int mlx5e_arfs_enable(struct mlx5e_priv *priv);
int mlx5e_arfs_disable(struct mlx5e_priv *priv);
int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
u16 rxq_index, u32 flow_id); u16 rxq_index, u32 flow_id);
#endif #endif
......
...@@ -72,14 +72,87 @@ struct arfs_rule { ...@@ -72,14 +72,87 @@ struct arfs_rule {
for (j = 0; j < ARFS_HASH_SIZE; j++) \ for (j = 0; j < ARFS_HASH_SIZE; j++) \
hlist_for_each_entry_safe(hn, tmp, &hash[j], hlist) hlist_for_each_entry_safe(hn, tmp, &hash[j], hlist)
static enum mlx5e_traffic_types arfs_get_tt(enum arfs_type type)
{
switch (type) {
case ARFS_IPV4_TCP:
return MLX5E_TT_IPV4_TCP;
case ARFS_IPV4_UDP:
return MLX5E_TT_IPV4_UDP;
case ARFS_IPV6_TCP:
return MLX5E_TT_IPV6_TCP;
case ARFS_IPV6_UDP:
return MLX5E_TT_IPV6_UDP;
default:
return -EINVAL;
}
}
static int arfs_disable(struct mlx5e_priv *priv)
{
struct mlx5_flow_destination dest;
u32 *tirn = priv->indir_tirn;
int err = 0;
int tt;
int i;
dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
for (i = 0; i < ARFS_NUM_TYPES; i++) {
dest.tir_num = tirn[i];
tt = arfs_get_tt(i);
/* Modify ttc rules destination to bypass the aRFS tables*/
err = mlx5_modify_rule_destination(priv->fs.ttc.rules[tt],
&dest);
if (err) {
netdev_err(priv->netdev,
"%s: modify ttc destination failed\n",
__func__);
return err;
}
}
return 0;
}
static void arfs_del_rules(struct mlx5e_priv *priv);
int mlx5e_arfs_disable(struct mlx5e_priv *priv)
{
arfs_del_rules(priv);
return arfs_disable(priv);
}
int mlx5e_arfs_enable(struct mlx5e_priv *priv)
{
struct mlx5_flow_destination dest;
int err = 0;
int tt;
int i;
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
for (i = 0; i < ARFS_NUM_TYPES; i++) {
dest.ft = priv->fs.arfs.arfs_tables[i].ft.t;
tt = arfs_get_tt(i);
/* Modify ttc rules destination to point on the aRFS FTs */
err = mlx5_modify_rule_destination(priv->fs.ttc.rules[tt],
&dest);
if (err) {
netdev_err(priv->netdev,
"%s: modify ttc destination failed err=%d\n",
__func__, err);
arfs_disable(priv);
return err;
}
}
return 0;
}
static void arfs_destroy_table(struct arfs_table *arfs_t) static void arfs_destroy_table(struct arfs_table *arfs_t)
{ {
mlx5_del_flow_rule(arfs_t->default_rule); mlx5_del_flow_rule(arfs_t->default_rule);
mlx5e_destroy_flow_table(&arfs_t->ft); mlx5e_destroy_flow_table(&arfs_t->ft);
} }
static void arfs_del_rules(struct mlx5e_priv *priv);
void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv) void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv)
{ {
int i; int i;
......
...@@ -456,6 +456,7 @@ static int mlx5e_set_channels(struct net_device *dev, ...@@ -456,6 +456,7 @@ static int mlx5e_set_channels(struct net_device *dev,
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
int ncv = mlx5e_get_max_num_channels(priv->mdev); int ncv = mlx5e_get_max_num_channels(priv->mdev);
unsigned int count = ch->combined_count; unsigned int count = ch->combined_count;
bool arfs_enabled;
bool was_opened; bool was_opened;
int err = 0; int err = 0;
...@@ -484,13 +485,27 @@ static int mlx5e_set_channels(struct net_device *dev, ...@@ -484,13 +485,27 @@ static int mlx5e_set_channels(struct net_device *dev,
if (was_opened) if (was_opened)
mlx5e_close_locked(dev); mlx5e_close_locked(dev);
arfs_enabled = dev->features & NETIF_F_NTUPLE;
if (arfs_enabled)
mlx5e_arfs_disable(priv);
priv->params.num_channels = count; priv->params.num_channels = count;
mlx5e_build_default_indir_rqt(priv->mdev, priv->params.indirection_rqt, mlx5e_build_default_indir_rqt(priv->mdev, priv->params.indirection_rqt,
MLX5E_INDIR_RQT_SIZE, count); MLX5E_INDIR_RQT_SIZE, count);
if (was_opened) if (was_opened)
err = mlx5e_open_locked(dev); err = mlx5e_open_locked(dev);
if (err)
goto out;
if (arfs_enabled) {
err = mlx5e_arfs_enable(priv);
if (err)
netdev_err(dev, "%s: mlx5e_arfs_enable failed: %d\n",
__func__, err);
}
out:
mutex_unlock(&priv->state_lock); mutex_unlock(&priv->state_lock);
return err; return err;
......
...@@ -2308,6 +2308,21 @@ static int set_feature_rx_vlan(struct net_device *netdev, bool enable) ...@@ -2308,6 +2308,21 @@ static int set_feature_rx_vlan(struct net_device *netdev, bool enable)
return err; return err;
} }
#ifdef CONFIG_RFS_ACCEL
static int set_feature_arfs(struct net_device *netdev, bool enable)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
int err;
if (enable)
err = mlx5e_arfs_enable(priv);
else
err = mlx5e_arfs_disable(priv);
return err;
}
#endif
static int mlx5e_handle_feature(struct net_device *netdev, static int mlx5e_handle_feature(struct net_device *netdev,
netdev_features_t wanted_features, netdev_features_t wanted_features,
netdev_features_t feature, netdev_features_t feature,
...@@ -2347,6 +2362,10 @@ static int mlx5e_set_features(struct net_device *netdev, ...@@ -2347,6 +2362,10 @@ static int mlx5e_set_features(struct net_device *netdev,
set_feature_rx_all); set_feature_rx_all);
err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_VLAN_CTAG_RX, err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_VLAN_CTAG_RX,
set_feature_rx_vlan); set_feature_rx_vlan);
#ifdef CONFIG_RFS_ACCEL
err |= mlx5e_handle_feature(netdev, features, NETIF_F_NTUPLE,
set_feature_arfs);
#endif
return err ? -EINVAL : 0; return err ? -EINVAL : 0;
} }
...@@ -2562,6 +2581,9 @@ static const struct net_device_ops mlx5e_netdev_ops_basic = { ...@@ -2562,6 +2581,9 @@ static const struct net_device_ops mlx5e_netdev_ops_basic = {
.ndo_set_features = mlx5e_set_features, .ndo_set_features = mlx5e_set_features,
.ndo_change_mtu = mlx5e_change_mtu, .ndo_change_mtu = mlx5e_change_mtu,
.ndo_do_ioctl = mlx5e_ioctl, .ndo_do_ioctl = mlx5e_ioctl,
#ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = mlx5e_rx_flow_steer,
#endif
}; };
static const struct net_device_ops mlx5e_netdev_ops_sriov = { static const struct net_device_ops mlx5e_netdev_ops_sriov = {
...@@ -2581,6 +2603,9 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = { ...@@ -2581,6 +2603,9 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = {
.ndo_add_vxlan_port = mlx5e_add_vxlan_port, .ndo_add_vxlan_port = mlx5e_add_vxlan_port,
.ndo_del_vxlan_port = mlx5e_del_vxlan_port, .ndo_del_vxlan_port = mlx5e_del_vxlan_port,
.ndo_features_check = mlx5e_features_check, .ndo_features_check = mlx5e_features_check,
#ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = mlx5e_rx_flow_steer,
#endif
.ndo_set_vf_mac = mlx5e_set_vf_mac, .ndo_set_vf_mac = mlx5e_set_vf_mac,
.ndo_set_vf_vlan = mlx5e_set_vf_vlan, .ndo_set_vf_vlan = mlx5e_set_vf_vlan,
.ndo_get_vf_config = mlx5e_get_vf_config, .ndo_get_vf_config = mlx5e_get_vf_config,
......
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