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: Maor Gottlieb <maorg@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
18c908e477
commit
45bf454ae8
@ -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 int mlx5e_arfs_enable(struct mlx5e_priv *priv)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline int mlx5e_arfs_disable(struct mlx5e_priv *priv)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
#else
|
||||
int mlx5e_arfs_create_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,
|
||||
u16 rxq_index, u32 flow_id);
|
||||
#endif
|
||||
|
@ -72,14 +72,87 @@ struct arfs_rule {
|
||||
for (j = 0; j < ARFS_HASH_SIZE; j++) \
|
||||
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)
|
||||
{
|
||||
mlx5_del_flow_rule(arfs_t->default_rule);
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
@ -456,6 +456,7 @@ static int mlx5e_set_channels(struct net_device *dev,
|
||||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
int ncv = mlx5e_get_max_num_channels(priv->mdev);
|
||||
unsigned int count = ch->combined_count;
|
||||
bool arfs_enabled;
|
||||
bool was_opened;
|
||||
int err = 0;
|
||||
|
||||
@ -484,13 +485,27 @@ static int mlx5e_set_channels(struct net_device *dev,
|
||||
if (was_opened)
|
||||
mlx5e_close_locked(dev);
|
||||
|
||||
arfs_enabled = dev->features & NETIF_F_NTUPLE;
|
||||
if (arfs_enabled)
|
||||
mlx5e_arfs_disable(priv);
|
||||
|
||||
priv->params.num_channels = count;
|
||||
mlx5e_build_default_indir_rqt(priv->mdev, priv->params.indirection_rqt,
|
||||
MLX5E_INDIR_RQT_SIZE, count);
|
||||
|
||||
if (was_opened)
|
||||
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);
|
||||
|
||||
return err;
|
||||
|
@ -2308,6 +2308,21 @@ static int set_feature_rx_vlan(struct net_device *netdev, bool enable)
|
||||
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,
|
||||
netdev_features_t wanted_features,
|
||||
netdev_features_t feature,
|
||||
@ -2347,6 +2362,10 @@ static int mlx5e_set_features(struct net_device *netdev,
|
||||
set_feature_rx_all);
|
||||
err |= mlx5e_handle_feature(netdev, features, NETIF_F_HW_VLAN_CTAG_RX,
|
||||
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;
|
||||
}
|
||||
@ -2562,6 +2581,9 @@ static const struct net_device_ops mlx5e_netdev_ops_basic = {
|
||||
.ndo_set_features = mlx5e_set_features,
|
||||
.ndo_change_mtu = mlx5e_change_mtu,
|
||||
.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 = {
|
||||
@ -2581,6 +2603,9 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = {
|
||||
.ndo_add_vxlan_port = mlx5e_add_vxlan_port,
|
||||
.ndo_del_vxlan_port = mlx5e_del_vxlan_port,
|
||||
.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_vlan = mlx5e_set_vf_vlan,
|
||||
.ndo_get_vf_config = mlx5e_get_vf_config,
|
||||
|
Loading…
Reference in New Issue
Block a user