mlxsw: spectrum: Implement chain template hinting
authorJiri Pirko <jiri@mellanox.com>
Mon, 23 Jul 2018 07:23:12 +0000 (09:23 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 24 Jul 2018 03:44:13 +0000 (20:44 -0700)
Since cld_flower provides information about the filter template for
specific chain, use this information in order to prepare a region.
Use the template to find out what elements are going to be used
and pass that down to mlxsw_sp_acl_tcam_group_add(). Later on, when the
first filter is inserted, the mlxsw_sp_acl_tcam_group_use_patterns()
function would use this element usage information instead of looking
up a pattern.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c

index 317c92d..0392285 100644 (file)
@@ -1455,6 +1455,11 @@ mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_acl_block *acl_block,
                return 0;
        case TC_CLSFLOWER_STATS:
                return mlxsw_sp_flower_stats(mlxsw_sp, acl_block, f);
+       case TC_CLSFLOWER_TMPLT_CREATE:
+               return mlxsw_sp_flower_tmplt_create(mlxsw_sp, acl_block, f);
+       case TC_CLSFLOWER_TMPLT_DESTROY:
+               mlxsw_sp_flower_tmplt_destroy(mlxsw_sp, acl_block, f);
+               return 0;
        default:
                return -EOPNOTSUPP;
        }
index 0160589..3db386c 100644 (file)
@@ -543,7 +543,8 @@ mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp,
 struct mlxsw_sp_acl_ruleset *
 mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
                         struct mlxsw_sp_acl_block *block, u32 chain_index,
-                        enum mlxsw_sp_acl_profile profile);
+                        enum mlxsw_sp_acl_profile profile,
+                        struct mlxsw_afk_element_usage *tmplt_elusage);
 void mlxsw_sp_acl_ruleset_put(struct mlxsw_sp *mlxsw_sp,
                              struct mlxsw_sp_acl_ruleset *ruleset);
 u16 mlxsw_sp_acl_ruleset_group_id(struct mlxsw_sp_acl_ruleset *ruleset);
@@ -667,6 +668,12 @@ void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp,
 int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
                          struct mlxsw_sp_acl_block *block,
                          struct tc_cls_flower_offload *f);
+int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp,
+                                struct mlxsw_sp_acl_block *block,
+                                struct tc_cls_flower_offload *f);
+void mlxsw_sp_flower_tmplt_destroy(struct mlxsw_sp *mlxsw_sp,
+                                  struct mlxsw_sp_acl_block *block,
+                                  struct tc_cls_flower_offload *f);
 
 /* spectrum_qdisc.c */
 int mlxsw_sp_tc_qdisc_init(struct mlxsw_sp_port *mlxsw_sp_port);
index 217621d..4a47391 100644 (file)
@@ -317,7 +317,8 @@ int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp,
 static struct mlxsw_sp_acl_ruleset *
 mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp,
                            struct mlxsw_sp_acl_block *block, u32 chain_index,
-                           const struct mlxsw_sp_acl_profile_ops *ops)
+                           const struct mlxsw_sp_acl_profile_ops *ops,
+                           struct mlxsw_afk_element_usage *tmplt_elusage)
 {
        struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
        struct mlxsw_sp_acl_ruleset *ruleset;
@@ -337,7 +338,8 @@ mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp,
        if (err)
                goto err_rhashtable_init;
 
-       err = ops->ruleset_add(mlxsw_sp, &acl->tcam, ruleset->priv);
+       err = ops->ruleset_add(mlxsw_sp, &acl->tcam, ruleset->priv,
+                              tmplt_elusage);
        if (err)
                goto err_ops_ruleset_add;
 
@@ -419,7 +421,8 @@ mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp,
 struct mlxsw_sp_acl_ruleset *
 mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
                         struct mlxsw_sp_acl_block *block, u32 chain_index,
-                        enum mlxsw_sp_acl_profile profile)
+                        enum mlxsw_sp_acl_profile profile,
+                        struct mlxsw_afk_element_usage *tmplt_elusage)
 {
        const struct mlxsw_sp_acl_profile_ops *ops;
        struct mlxsw_sp_acl *acl = mlxsw_sp->acl;
@@ -434,7 +437,8 @@ mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
                mlxsw_sp_acl_ruleset_ref_inc(ruleset);
                return ruleset;
        }
-       return mlxsw_sp_acl_ruleset_create(mlxsw_sp, block, chain_index, ops);
+       return mlxsw_sp_acl_ruleset_create(mlxsw_sp, block, chain_index, ops,
+                                          tmplt_elusage);
 }
 
 void mlxsw_sp_acl_ruleset_put(struct mlxsw_sp *mlxsw_sp,
index e06d7d9..310fd87 100644 (file)
@@ -189,6 +189,8 @@ struct mlxsw_sp_acl_tcam_group {
        struct mlxsw_sp_acl_tcam_group_ops *ops;
        const struct mlxsw_sp_acl_tcam_pattern *patterns;
        unsigned int patterns_count;
+       bool tmplt_elusage_set;
+       struct mlxsw_afk_element_usage tmplt_elusage;
 };
 
 struct mlxsw_sp_acl_tcam_chunk {
@@ -234,13 +236,19 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp *mlxsw_sp,
                            struct mlxsw_sp_acl_tcam *tcam,
                            struct mlxsw_sp_acl_tcam_group *group,
                            const struct mlxsw_sp_acl_tcam_pattern *patterns,
-                           unsigned int patterns_count)
+                           unsigned int patterns_count,
+                           struct mlxsw_afk_element_usage *tmplt_elusage)
 {
        int err;
 
        group->tcam = tcam;
        group->patterns = patterns;
        group->patterns_count = patterns_count;
+       if (tmplt_elusage) {
+               group->tmplt_elusage_set = true;
+               memcpy(&group->tmplt_elusage, tmplt_elusage,
+                      sizeof(group->tmplt_elusage));
+       }
        INIT_LIST_HEAD(&group->region_list);
        err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id);
        if (err)
@@ -449,6 +457,15 @@ mlxsw_sp_acl_tcam_group_use_patterns(struct mlxsw_sp_acl_tcam_group *group,
        const struct mlxsw_sp_acl_tcam_pattern *pattern;
        int i;
 
+       /* In case the template is set, we don't have to look up the pattern
+        * and just use the template.
+        */
+       if (group->tmplt_elusage_set) {
+               memcpy(out, &group->tmplt_elusage, sizeof(*out));
+               WARN_ON(!mlxsw_afk_element_usage_subset(elusage, out));
+               return;
+       }
+
        for (i = 0; i < group->patterns_count; i++) {
                pattern = &group->patterns[i];
                mlxsw_afk_element_usage_fill(out, pattern->elements,
@@ -865,13 +882,15 @@ struct mlxsw_sp_acl_tcam_flower_rule {
 static int
 mlxsw_sp_acl_tcam_flower_ruleset_add(struct mlxsw_sp *mlxsw_sp,
                                     struct mlxsw_sp_acl_tcam *tcam,
-                                    void *ruleset_priv)
+                                    void *ruleset_priv,
+                                    struct mlxsw_afk_element_usage *tmplt_elusage)
 {
        struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv;
 
        return mlxsw_sp_acl_tcam_group_add(mlxsw_sp, tcam, &ruleset->group,
                                           mlxsw_sp_acl_tcam_patterns,
-                                          MLXSW_SP_ACL_TCAM_PATTERNS_COUNT);
+                                          MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
+                                          tmplt_elusage);
 }
 
 static void
index 68551da..6403ec4 100644 (file)
@@ -64,7 +64,8 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
 struct mlxsw_sp_acl_profile_ops {
        size_t ruleset_priv_size;
        int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp,
-                          struct mlxsw_sp_acl_tcam *tcam, void *ruleset_priv);
+                          struct mlxsw_sp_acl_tcam *tcam, void *ruleset_priv,
+                          struct mlxsw_afk_element_usage *tmplt_elusage);
        void (*ruleset_del)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv);
        int (*ruleset_bind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
                            struct mlxsw_sp_port *mlxsw_sp_port,
index 201761a..b3cb618 100644 (file)
@@ -414,7 +414,7 @@ int mlxsw_sp_flower_replace(struct mlxsw_sp *mlxsw_sp,
 
        ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
                                           f->common.chain_index,
-                                          MLXSW_SP_ACL_PROFILE_FLOWER);
+                                          MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
        if (IS_ERR(ruleset))
                return PTR_ERR(ruleset);
 
@@ -458,7 +458,7 @@ void mlxsw_sp_flower_destroy(struct mlxsw_sp *mlxsw_sp,
 
        ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
                                           f->common.chain_index,
-                                          MLXSW_SP_ACL_PROFILE_FLOWER);
+                                          MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
        if (IS_ERR(ruleset))
                return;
 
@@ -484,7 +484,7 @@ int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
 
        ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
                                           f->common.chain_index,
-                                          MLXSW_SP_ACL_PROFILE_FLOWER);
+                                          MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
        if (WARN_ON(IS_ERR(ruleset)))
                return -EINVAL;
 
@@ -506,3 +506,41 @@ err_rule_get_stats:
        mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
        return err;
 }
+
+int mlxsw_sp_flower_tmplt_create(struct mlxsw_sp *mlxsw_sp,
+                                struct mlxsw_sp_acl_block *block,
+                                struct tc_cls_flower_offload *f)
+{
+       struct mlxsw_sp_acl_ruleset *ruleset;
+       struct mlxsw_sp_acl_rule_info rulei;
+       int err;
+
+       memset(&rulei, 0, sizeof(rulei));
+       err = mlxsw_sp_flower_parse(mlxsw_sp, block, &rulei, f);
+       if (err)
+               return err;
+       ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
+                                          f->common.chain_index,
+                                          MLXSW_SP_ACL_PROFILE_FLOWER,
+                                          &rulei.values.elusage);
+       if (IS_ERR(ruleset))
+               return PTR_ERR(ruleset);
+       /* keep the reference to the ruleset */
+       return 0;
+}
+
+void mlxsw_sp_flower_tmplt_destroy(struct mlxsw_sp *mlxsw_sp,
+                                  struct mlxsw_sp_acl_block *block,
+                                  struct tc_cls_flower_offload *f)
+{
+       struct mlxsw_sp_acl_ruleset *ruleset;
+
+       ruleset = mlxsw_sp_acl_ruleset_get(mlxsw_sp, block,
+                                          f->common.chain_index,
+                                          MLXSW_SP_ACL_PROFILE_FLOWER, NULL);
+       if (IS_ERR(ruleset))
+               return;
+       /* put the reference to the ruleset kept in create */
+       mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
+       mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
+}