Skip to content

Commit

Permalink
net/mlx5e: Introduce root ft concept for representors netdevs
Browse files Browse the repository at this point in the history
Uplink representor traffic will be redirected to an empty root ft rather
than directly to a direct tir or ttc table, this root ft will be empty and
will be used as a link for auto-chaining with ttc table or ethtool tables
in downstream patches.

On load, fs core will connect uplink rep root_ft with ttc table.  In case
ethtool steering will be used, fs core will auto connect root_ft with
the ethtool bypass tables, which will be connected with the ttc table.

vport_rx_rule[uplink_rep]->root_ft->ethtool->ttc.

For non-uplink representors, for simplicity root_ft will always point at
ttc table, hence the replace vport_rx rule logic is removed.

vport_rx_rule[non_uplink_rep]->root_ft(ttc).

For now ethtool steering support can only be available on uplink rep.

Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Roi Dayan <roid@mellanox.com>
  • Loading branch information
Saeed Mahameed committed Mar 9, 2020
1 parent cc617ce commit 20f7b37
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 53 deletions.
116 changes: 65 additions & 51 deletions drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,25 +253,6 @@ static int mlx5e_rep_set_ringparam(struct net_device *dev,
return mlx5e_ethtool_set_ringparam(priv, param);
}

static int mlx5e_replace_rep_vport_rx_rule(struct mlx5e_priv *priv,
struct mlx5_flow_destination *dest)
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *rep = rpriv->rep;
struct mlx5_flow_handle *flow_rule;

flow_rule = mlx5_eswitch_create_vport_rx_rule(esw,
rep->vport,
dest);
if (IS_ERR(flow_rule))
return PTR_ERR(flow_rule);

mlx5_del_flow_rules(rpriv->vport_rx_rule);
rpriv->vport_rx_rule = flow_rule;
return 0;
}

static void mlx5e_rep_get_channels(struct net_device *dev,
struct ethtool_channels *ch)
{
Expand All @@ -284,33 +265,8 @@ static int mlx5e_rep_set_channels(struct net_device *dev,
struct ethtool_channels *ch)
{
struct mlx5e_priv *priv = netdev_priv(dev);
u16 curr_channels_amount = priv->channels.params.num_channels;
u32 new_channels_amount = ch->combined_count;
struct mlx5_flow_destination new_dest;
int err = 0;

err = mlx5e_ethtool_set_channels(priv, ch);
if (err)
return err;

if (curr_channels_amount == 1 && new_channels_amount > 1) {
new_dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
new_dest.ft = priv->fs.ttc.ft.t;
} else if (new_channels_amount == 1 && curr_channels_amount > 1) {
new_dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
new_dest.tir_num = priv->direct_tir[0].tirn;
} else {
return 0;
}

err = mlx5e_replace_rep_vport_rx_rule(priv, &new_dest);
if (err) {
netdev_warn(priv->netdev, "Failed to update vport rx rule, when going from (%d) channels to (%d) channels\n",
curr_channels_amount, new_channels_amount);
return err;
}

return 0;
return mlx5e_ethtool_set_channels(priv, ch);
}

static int mlx5e_rep_get_coalesce(struct net_device *netdev,
Expand Down Expand Up @@ -1596,6 +1552,8 @@ static void mlx5e_cleanup_rep(struct mlx5e_priv *priv)

static int mlx5e_create_rep_ttc_table(struct mlx5e_priv *priv)
{
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *rep = rpriv->rep;
struct ttc_params ttc_params = {};
int tt, err;

Expand All @@ -1605,6 +1563,11 @@ static int mlx5e_create_rep_ttc_table(struct mlx5e_priv *priv)
/* The inner_ttc in the ttc params is intentionally not set */
ttc_params.any_tt_tirn = priv->direct_tir[0].tirn;
mlx5e_set_ttc_ft_params(&ttc_params);

if (rep->vport != MLX5_VPORT_UPLINK)
/* To give uplik rep TTC a lower level for chaining from root ft */
ttc_params.ft_attr.level = MLX5E_TTC_FT_LEVEL + 1;

for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
ttc_params.indir_tirn[tt] = priv->indir_tir[tt].tirn;

Expand All @@ -1616,6 +1579,51 @@ static int mlx5e_create_rep_ttc_table(struct mlx5e_priv *priv)
return 0;
}

static int mlx5e_create_rep_root_ft(struct mlx5e_priv *priv)
{
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *rep = rpriv->rep;
struct mlx5_flow_table_attr ft_attr = {};
struct mlx5_flow_namespace *ns;
int err = 0;

if (rep->vport != MLX5_VPORT_UPLINK) {
/* non uplik reps will skip any bypass tables and go directly to
* their own ttc
*/
rpriv->root_ft = priv->fs.ttc.ft.t;
return 0;
}

/* uplink root ft will be used to auto chain, to ethtool or ttc tables */
ns = mlx5_get_flow_namespace(priv->mdev, MLX5_FLOW_NAMESPACE_OFFLOADS);
if (!ns) {
netdev_err(priv->netdev, "Failed to get reps offloads namespace\n");
return -EOPNOTSUPP;
}

ft_attr.max_fte = 0; /* Empty table, miss rule will always point to next table */
ft_attr.level = 1;

rpriv->root_ft = mlx5_create_flow_table(ns, &ft_attr);
if (IS_ERR(rpriv->root_ft)) {
err = PTR_ERR(rpriv->root_ft);
rpriv->root_ft = NULL;
}

return err;
}

static void mlx5e_destroy_rep_root_ft(struct mlx5e_priv *priv)
{
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *rep = rpriv->rep;

if (rep->vport != MLX5_VPORT_UPLINK)
return;
mlx5_destroy_flow_table(rpriv->root_ft);
}

static int mlx5e_create_rep_vport_rx_rule(struct mlx5e_priv *priv)
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
Expand All @@ -1624,11 +1632,10 @@ static int mlx5e_create_rep_vport_rx_rule(struct mlx5e_priv *priv)
struct mlx5_flow_handle *flow_rule;
struct mlx5_flow_destination dest;

dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
dest.tir_num = priv->direct_tir[0].tirn;
flow_rule = mlx5_eswitch_create_vport_rx_rule(esw,
rep->vport,
&dest);
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
dest.ft = rpriv->root_ft;

flow_rule = mlx5_eswitch_create_vport_rx_rule(esw, rep->vport, &dest);
if (IS_ERR(flow_rule))
return PTR_ERR(flow_rule);
rpriv->vport_rx_rule = flow_rule;
Expand Down Expand Up @@ -1668,12 +1675,18 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
if (err)
goto err_destroy_direct_tirs;

err = mlx5e_create_rep_vport_rx_rule(priv);
err = mlx5e_create_rep_root_ft(priv);
if (err)
goto err_destroy_ttc_table;

err = mlx5e_create_rep_vport_rx_rule(priv);
if (err)
goto err_destroy_root_ft;

return 0;

err_destroy_root_ft:
mlx5e_destroy_rep_root_ft(priv);
err_destroy_ttc_table:
mlx5e_destroy_ttc_table(priv, &priv->fs.ttc);
err_destroy_direct_tirs:
Expand All @@ -1694,6 +1707,7 @@ static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
struct mlx5e_rep_priv *rpriv = priv->ppriv;

mlx5_del_flow_rules(rpriv->vport_rx_rule);
mlx5e_destroy_rep_root_ft(priv);
mlx5e_destroy_ttc_table(priv, &priv->fs.ttc);
mlx5e_destroy_direct_tirs(priv, priv->direct_tir);
mlx5e_destroy_indirect_tirs(priv, false);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ struct mlx5e_rep_priv {
struct mlx5_eswitch_rep *rep;
struct mlx5e_neigh_update_table neigh_update;
struct net_device *netdev;
struct mlx5_flow_table *root_ft;
struct mlx5_flow_handle *vport_rx_rule;
struct list_head vport_sqs_list;
struct mlx5_rep_uplink_priv uplink_priv; /* valid for uplink rep */
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
#define ANCHOR_NUM_PRIOS 1
#define ANCHOR_MIN_LEVEL (BY_PASS_MIN_LEVEL + 1)

#define OFFLOADS_MAX_FT 1
#define OFFLOADS_MAX_FT 2
#define OFFLOADS_NUM_PRIOS 1
#define OFFLOADS_MIN_LEVEL (ANCHOR_MIN_LEVEL + 1)

Expand Down Expand Up @@ -145,7 +145,7 @@ static struct init_tree_node {
ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF,
ADD_MULTIPLE_PRIO(LAG_NUM_PRIOS,
LAG_PRIO_NUM_LEVELS))),
ADD_PRIO(0, OFFLOADS_MIN_LEVEL, 0, {},
ADD_PRIO(0, OFFLOADS_MIN_LEVEL, 0, FS_CHAINING_CAPS,
ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF,
ADD_MULTIPLE_PRIO(OFFLOADS_NUM_PRIOS,
OFFLOADS_MAX_FT))),
Expand Down

0 comments on commit 20f7b37

Please sign in to comment.