net/mlx5: E-Switch, Introduce global tables
authorPaul Blakey <paulb@mellanox.com>
Thu, 12 Mar 2020 10:23:10 +0000 (12:23 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 12 Mar 2020 22:00:39 +0000 (15:00 -0700)
Currently, flow tables are automatically connected according to their
<chain,prio,level> tuple.

Introduce global tables which are flow tables that are detached from the
eswitch chains processing, and will be connected by explicitly referencing
them from multiple chains.

Add this new table type, and allow connecting them by refenece.

Signed-off-by: Paul Blakey <paulb@mellanox.com>
Reviewed-by: Oz Shlomo <ozsh@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.h

index ee36a8ab8e65fc3fe3e0e0641073227edeeddd2e..dae0f3e5ada92b8842909f03a8239f9cda6ed3a3 100644 (file)
@@ -421,6 +421,8 @@ struct mlx5_esw_flow_attr {
        u16     prio;
        u32     dest_chain;
        u32     flags;
+       struct mlx5_flow_table *fdb;
+       struct mlx5_flow_table *dest_ft;
        struct mlx5e_tc_flow_parse_attr *parse_attr;
 };
 
index 5e751d7749db601d0995e950f6af46ed8ae4759b..0c4bf69f6c47b3542d6ad6022c435c352519adae 100644 (file)
@@ -324,7 +324,12 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
                struct mlx5_flow_table *ft;
 
-               if (attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) {
+               if (attr->dest_ft) {
+                       flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
+                       dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
+                       dest[i].ft = attr->dest_ft;
+                       i++;
+               } else if (attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) {
                        flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
                        dest[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
                        dest[i].ft = mlx5_esw_chains_get_tc_end_ft(esw);
@@ -378,8 +383,11 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
        if (split) {
                fdb = esw_vport_tbl_get(esw, attr);
        } else {
-               fdb = mlx5_esw_chains_get_table(esw, attr->chain, attr->prio,
-                                               0);
+               if (attr->chain || attr->prio)
+                       fdb = mlx5_esw_chains_get_table(esw, attr->chain,
+                                                       attr->prio, 0);
+               else
+                       fdb = attr->fdb;
                mlx5_eswitch_set_rule_source_port(esw, spec, attr);
        }
        if (IS_ERR(fdb)) {
@@ -402,7 +410,7 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
 err_add_rule:
        if (split)
                esw_vport_tbl_put(esw, attr);
-       else
+       else if (attr->chain || attr->prio)
                mlx5_esw_chains_put_table(esw, attr->chain, attr->prio, 0);
 err_esw_get:
        if (!(attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) && attr->dest_chain)
@@ -499,7 +507,7 @@ __mlx5_eswitch_del_rule(struct mlx5_eswitch *esw,
        } else {
                if (split)
                        esw_vport_tbl_put(esw, attr);
-               else
+               else if (attr->chain || attr->prio)
                        mlx5_esw_chains_put_table(esw, attr->chain, attr->prio,
                                                  0);
                if (attr->dest_chain)
index ca3bbf84a5be8ee3c92608843cfe52ca3f69cb58..84e3313e3bf148e3b2fbce57165eb44701d38b26 100644 (file)
@@ -722,6 +722,36 @@ mlx5_esw_chains_get_tc_end_ft(struct mlx5_eswitch *esw)
        return tc_end_fdb(esw);
 }
 
+struct mlx5_flow_table *
+mlx5_esw_chains_create_global_table(struct mlx5_eswitch *esw)
+{
+       int chain, prio, level, err;
+
+       if (!fdb_ignore_flow_level_supported(esw)) {
+               err = -EOPNOTSUPP;
+
+               esw_warn(esw->dev,
+                        "Couldn't create global flow table, ignore_flow_level not supported.");
+               goto err_ignore;
+       }
+
+       chain = mlx5_esw_chains_get_chain_range(esw),
+       prio = mlx5_esw_chains_get_prio_range(esw);
+       level = mlx5_esw_chains_get_level_range(esw);
+
+       return mlx5_esw_chains_create_fdb_table(esw, chain, prio, level);
+
+err_ignore:
+       return ERR_PTR(err);
+}
+
+void
+mlx5_esw_chains_destroy_global_table(struct mlx5_eswitch *esw,
+                                    struct mlx5_flow_table *ft)
+{
+       mlx5_esw_chains_destroy_fdb_table(esw, ft);
+}
+
 static int
 mlx5_esw_chains_init(struct mlx5_eswitch *esw)
 {
index e806d8de868ea8b62c4e59da1cf4a70663d27047..c7bc609acb91817ea88854220d4c97f045c91fb0 100644 (file)
@@ -25,6 +25,12 @@ mlx5_esw_chains_put_table(struct mlx5_eswitch *esw, u32 chain, u32 prio,
 struct mlx5_flow_table *
 mlx5_esw_chains_get_tc_end_ft(struct mlx5_eswitch *esw);
 
+struct mlx5_flow_table *
+mlx5_esw_chains_create_global_table(struct mlx5_eswitch *esw);
+void
+mlx5_esw_chains_destroy_global_table(struct mlx5_eswitch *esw,
+                                    struct mlx5_flow_table *ft);
+
 int mlx5_esw_chains_create(struct mlx5_eswitch *esw);
 void mlx5_esw_chains_destroy(struct mlx5_eswitch *esw);