Commit 655dc3d2 authored by Or Gerlitz's avatar Or Gerlitz Committed by Saeed Mahameed

net/mlx5e: Use shared table for offloaded TC eswitch flows

Currently, each representor netdev use their own hash table to keep
the mapping from TC flow (f->cookie) to the driver offloaded instance.
The table is the one which originally was added for offloading TC NIC
(not eswitch) rules.

This scheme breaks when the core TC code calls us to add the same flow
twice, (e.g under egdev use case) since we don't spot that and offload
a 2nd flow into the HW with the wrong source vport.

As a pre-step to solve that, we move to use a single table which keeps
all offloaded TC eswitch flows. The table is located at the eswitch
uplink representor object.
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Reviewed-by: default avatarPaul Blakey <paulb@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 05866c82
...@@ -4462,7 +4462,7 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv) ...@@ -4462,7 +4462,7 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
goto err_destroy_direct_tirs; goto err_destroy_direct_tirs;
} }
err = mlx5e_tc_init(priv); err = mlx5e_tc_nic_init(priv);
if (err) if (err)
goto err_destroy_flow_steering; goto err_destroy_flow_steering;
...@@ -4483,7 +4483,7 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv) ...@@ -4483,7 +4483,7 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv) static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv)
{ {
mlx5e_tc_cleanup(priv); mlx5e_tc_nic_cleanup(priv);
mlx5e_destroy_flow_steering(priv); mlx5e_destroy_flow_steering(priv);
mlx5e_destroy_direct_tirs(priv); mlx5e_destroy_direct_tirs(priv);
mlx5e_destroy_indirect_tirs(priv); mlx5e_destroy_indirect_tirs(priv);
......
...@@ -981,14 +981,8 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) ...@@ -981,14 +981,8 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
} }
rpriv->vport_rx_rule = flow_rule; rpriv->vport_rx_rule = flow_rule;
err = mlx5e_tc_init(priv);
if (err)
goto err_del_flow_rule;
return 0; return 0;
err_del_flow_rule:
mlx5_del_flow_rules(rpriv->vport_rx_rule);
err_destroy_direct_tirs: err_destroy_direct_tirs:
mlx5e_destroy_direct_tirs(priv); mlx5e_destroy_direct_tirs(priv);
err_destroy_direct_rqts: err_destroy_direct_rqts:
...@@ -1000,7 +994,6 @@ static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv) ...@@ -1000,7 +994,6 @@ static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
{ {
struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5e_rep_priv *rpriv = priv->ppriv;
mlx5e_tc_cleanup(priv);
mlx5_del_flow_rules(rpriv->vport_rx_rule); mlx5_del_flow_rules(rpriv->vport_rx_rule);
mlx5e_destroy_direct_tirs(priv); mlx5e_destroy_direct_tirs(priv);
mlx5e_destroy_direct_rqts(priv); mlx5e_destroy_direct_rqts(priv);
...@@ -1058,8 +1051,15 @@ mlx5e_nic_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) ...@@ -1058,8 +1051,15 @@ mlx5e_nic_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
if (err) if (err)
goto err_remove_sqs; goto err_remove_sqs;
/* init shared tc flow table */
err = mlx5e_tc_esw_init(&rpriv->tc_ht);
if (err)
goto err_neigh_cleanup;
return 0; return 0;
err_neigh_cleanup:
mlx5e_rep_neigh_cleanup(rpriv);
err_remove_sqs: err_remove_sqs:
mlx5e_remove_sqs_fwd_rules(priv); mlx5e_remove_sqs_fwd_rules(priv);
return err; return err;
...@@ -1074,9 +1074,8 @@ mlx5e_nic_rep_unload(struct mlx5_eswitch_rep *rep) ...@@ -1074,9 +1074,8 @@ mlx5e_nic_rep_unload(struct mlx5_eswitch_rep *rep)
if (test_bit(MLX5E_STATE_OPENED, &priv->state)) if (test_bit(MLX5E_STATE_OPENED, &priv->state))
mlx5e_remove_sqs_fwd_rules(priv); mlx5e_remove_sqs_fwd_rules(priv);
/* clean (and re-init) existing uplink offloaded TC rules */ /* clean uplink offloaded TC rules, delete shared tc flow table */
mlx5e_tc_cleanup(priv); mlx5e_tc_esw_cleanup(&rpriv->tc_ht);
mlx5e_tc_init(priv);
mlx5e_rep_neigh_cleanup(rpriv); mlx5e_rep_neigh_cleanup(rpriv);
} }
......
...@@ -59,6 +59,7 @@ struct mlx5e_rep_priv { ...@@ -59,6 +59,7 @@ struct mlx5e_rep_priv {
struct net_device *netdev; struct net_device *netdev;
struct mlx5_flow_handle *vport_rx_rule; struct mlx5_flow_handle *vport_rx_rule;
struct list_head vport_sqs_list; struct list_head vport_sqs_list;
struct rhashtable tc_ht; /* valid for uplink rep */
}; };
static inline static inline
......
...@@ -76,6 +76,7 @@ enum { ...@@ -76,6 +76,7 @@ enum {
struct mlx5e_tc_flow { struct mlx5e_tc_flow {
struct rhash_head node; struct rhash_head node;
struct mlx5e_priv *priv;
u64 cookie; u64 cookie;
u8 flags; u8 flags;
struct mlx5_flow_handle *rule; struct mlx5_flow_handle *rule;
...@@ -2643,6 +2644,13 @@ static const struct rhashtable_params tc_ht_params = { ...@@ -2643,6 +2644,13 @@ static const struct rhashtable_params tc_ht_params = {
static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv) static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv)
{ {
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5e_rep_priv *uplink_rpriv;
if (MLX5_VPORT_MANAGER(priv->mdev) && esw->mode == SRIOV_OFFLOADS) {
uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
return &uplink_rpriv->tc_ht;
} else
return &priv->fs.tc.ht; return &priv->fs.tc.ht;
} }
...@@ -2675,6 +2683,7 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, ...@@ -2675,6 +2683,7 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv,
flow->cookie = f->cookie; flow->cookie = f->cookie;
flow->flags = flow_flags; flow->flags = flow_flags;
flow->priv = priv;
err = parse_cls_flower(priv, flow, &parse_attr->spec, f); err = parse_cls_flower(priv, flow, &parse_attr->spec, f);
if (err < 0) if (err < 0)
...@@ -2766,7 +2775,7 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv, ...@@ -2766,7 +2775,7 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
return 0; return 0;
} }
int mlx5e_tc_init(struct mlx5e_priv *priv) int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
{ {
struct mlx5e_tc_table *tc = &priv->fs.tc; struct mlx5e_tc_table *tc = &priv->fs.tc;
...@@ -2779,20 +2788,30 @@ int mlx5e_tc_init(struct mlx5e_priv *priv) ...@@ -2779,20 +2788,30 @@ int mlx5e_tc_init(struct mlx5e_priv *priv)
static void _mlx5e_tc_del_flow(void *ptr, void *arg) static void _mlx5e_tc_del_flow(void *ptr, void *arg)
{ {
struct mlx5e_tc_flow *flow = ptr; struct mlx5e_tc_flow *flow = ptr;
struct mlx5e_priv *priv = arg; struct mlx5e_priv *priv = flow->priv;
mlx5e_tc_del_flow(priv, flow); mlx5e_tc_del_flow(priv, flow);
kfree(flow); kfree(flow);
} }
void mlx5e_tc_cleanup(struct mlx5e_priv *priv) void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv)
{ {
struct mlx5e_tc_table *tc = &priv->fs.tc; struct mlx5e_tc_table *tc = &priv->fs.tc;
rhashtable_free_and_destroy(&tc->ht, _mlx5e_tc_del_flow, priv); rhashtable_free_and_destroy(&tc->ht, _mlx5e_tc_del_flow, NULL);
if (!IS_ERR_OR_NULL(tc->t)) { if (!IS_ERR_OR_NULL(tc->t)) {
mlx5_destroy_flow_table(tc->t); mlx5_destroy_flow_table(tc->t);
tc->t = NULL; tc->t = NULL;
} }
} }
int mlx5e_tc_esw_init(struct rhashtable *tc_ht)
{
return rhashtable_init(tc_ht, &tc_ht_params);
}
void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht)
{
rhashtable_free_and_destroy(tc_ht, _mlx5e_tc_del_flow, NULL);
}
...@@ -45,8 +45,11 @@ enum { ...@@ -45,8 +45,11 @@ enum {
MLX5E_TC_LAST_EXPORTED_BIT = 1, MLX5E_TC_LAST_EXPORTED_BIT = 1,
}; };
int mlx5e_tc_init(struct mlx5e_priv *priv); int mlx5e_tc_nic_init(struct mlx5e_priv *priv);
void mlx5e_tc_cleanup(struct mlx5e_priv *priv); void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv);
int mlx5e_tc_esw_init(struct rhashtable *tc_ht);
void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht);
int mlx5e_configure_flower(struct mlx5e_priv *priv, int mlx5e_configure_flower(struct mlx5e_priv *priv,
struct tc_cls_flower_offload *f, int flags); struct tc_cls_flower_offload *f, int flags);
...@@ -71,8 +74,8 @@ static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv) ...@@ -71,8 +74,8 @@ static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv)
} }
#else /* CONFIG_MLX5_ESWITCH */ #else /* CONFIG_MLX5_ESWITCH */
static inline int mlx5e_tc_init(struct mlx5e_priv *priv) { return 0; } static inline int mlx5e_tc_nic_init(struct mlx5e_priv *priv) { return 0; }
static inline void mlx5e_tc_cleanup(struct mlx5e_priv *priv) {} static inline void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) {}
static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv) { return 0; } static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv) { return 0; }
#endif #endif
......
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