mlxsw: spectrum_acl: Add replace rule action operation
authorNir Dotan <nird@mellanox.com>
Mon, 10 Dec 2018 07:11:41 +0000 (07:11 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 12 Dec 2018 07:01:33 +0000 (23:01 -0800)
Multicast routes actions may be updated after creation. An example for that
is an addition of an egress interface to an existing route.
So far, as tc flower API dictated, ACL rules were either created or
deleted. Since multicast routes in Spectrum-2 are written to ACL as any
rule, it is required to allow the update of a rule's action as it may
change.

Add methods and operations to support updating rule's action. This is
supported only for Spectrum-2.

Signed-off-by: Nir Dotan <nird@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h

index fa60c74..edd397f 100644 (file)
@@ -658,6 +658,9 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp,
                          struct mlxsw_sp_acl_rule *rule);
 void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp,
                           struct mlxsw_sp_acl_rule *rule);
+int mlxsw_sp_acl_rule_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                    struct mlxsw_sp_acl_rule *rule,
+                                    struct mlxsw_afa_block *afa_block);
 struct mlxsw_sp_acl_rule *
 mlxsw_sp_acl_rule_lookup(struct mlxsw_sp *mlxsw_sp,
                         struct mlxsw_sp_acl_ruleset *ruleset,
@@ -702,6 +705,10 @@ struct mlxsw_sp_acl_tcam_ops {
        void (*entry_del)(struct mlxsw_sp *mlxsw_sp,
                          void *region_priv, void *chunk_priv,
                          void *entry_priv);
+       int (*entry_action_replace)(struct mlxsw_sp *mlxsw_sp,
+                                   void *region_priv, void *chunk_priv,
+                                   void *entry_priv,
+                                   struct mlxsw_sp_acl_rule_info *rulei);
        int (*entry_activity_get)(struct mlxsw_sp *mlxsw_sp,
                                  void *region_priv, void *entry_priv,
                                  bool *activity);
index 2a9eac9..677526e 100644 (file)
@@ -193,6 +193,15 @@ static void mlxsw_sp1_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
 }
 
 static int
+mlxsw_sp1_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                       void *region_priv, void *chunk_priv,
+                                       void *entry_priv,
+                                       struct mlxsw_sp_acl_rule_info *rulei)
+{
+       return -EOPNOTSUPP;
+}
+
+static int
 mlxsw_sp1_acl_tcam_region_entry_activity_get(struct mlxsw_sp *mlxsw_sp,
                                             struct mlxsw_sp_acl_tcam_region *_region,
                                             unsigned int offset,
@@ -240,5 +249,6 @@ const struct mlxsw_sp_acl_tcam_ops mlxsw_sp1_acl_tcam_ops = {
        .entry_priv_size        = sizeof(struct mlxsw_sp1_acl_tcam_entry),
        .entry_add              = mlxsw_sp1_acl_tcam_entry_add,
        .entry_del              = mlxsw_sp1_acl_tcam_entry_del,
+       .entry_action_replace   = mlxsw_sp1_acl_tcam_entry_action_replace,
        .entry_activity_get     = mlxsw_sp1_acl_tcam_entry_activity_get,
 };
index 62e6cf4..234ab51 100644 (file)
@@ -211,6 +211,23 @@ static void mlxsw_sp2_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
 }
 
 static int
+mlxsw_sp2_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                       void *region_priv, void *chunk_priv,
+                                       void *entry_priv,
+                                       struct mlxsw_sp_acl_rule_info *rulei)
+{
+       struct mlxsw_sp2_acl_tcam_region *region = region_priv;
+       struct mlxsw_sp2_acl_tcam_chunk *chunk = chunk_priv;
+       struct mlxsw_sp2_acl_tcam_entry *entry = entry_priv;
+
+       entry->act_block = rulei->act_block;
+       return mlxsw_sp_acl_atcam_entry_action_replace(mlxsw_sp,
+                                                      &region->aregion,
+                                                      &chunk->achunk,
+                                                      &entry->aentry, rulei);
+}
+
+static int
 mlxsw_sp2_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp,
                                      void *region_priv, void *entry_priv,
                                      bool *activity)
@@ -235,5 +252,6 @@ const struct mlxsw_sp_acl_tcam_ops mlxsw_sp2_acl_tcam_ops = {
        .entry_priv_size        = sizeof(struct mlxsw_sp2_acl_tcam_entry),
        .entry_add              = mlxsw_sp2_acl_tcam_entry_add,
        .entry_del              = mlxsw_sp2_acl_tcam_entry_del,
+       .entry_action_replace   = mlxsw_sp2_acl_tcam_entry_action_replace,
        .entry_activity_get     = mlxsw_sp2_acl_tcam_entry_activity_get,
 };
index c4f9238..44bbe7c 100644 (file)
@@ -721,6 +721,21 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp,
        ops->rule_del(mlxsw_sp, rule->priv);
 }
 
+int mlxsw_sp_acl_rule_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                    struct mlxsw_sp_acl_rule *rule,
+                                    struct mlxsw_afa_block *afa_block)
+{
+       struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
+       const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
+       struct mlxsw_sp_acl_rule_info *rulei;
+
+       rulei = mlxsw_sp_acl_rule_rulei(rule);
+       rulei->act_block = afa_block;
+
+       return ops->rule_action_replace(mlxsw_sp, ruleset->priv, rule->priv,
+                                       rule->rulei);
+}
+
 struct mlxsw_sp_acl_rule *
 mlxsw_sp_acl_rule_lookup(struct mlxsw_sp *mlxsw_sp,
                         struct mlxsw_sp_acl_ruleset *ruleset,
index e7bd873..75f11c2 100644 (file)
@@ -438,6 +438,34 @@ mlxsw_sp_acl_atcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp,
 }
 
 static int
+mlxsw_sp_acl_atcam_region_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                              struct mlxsw_sp_acl_atcam_region *aregion,
+                                              struct mlxsw_sp_acl_atcam_entry *aentry,
+                                              struct mlxsw_sp_acl_rule_info *rulei)
+{
+       struct mlxsw_sp_acl_atcam_lkey_id *lkey_id = aentry->lkey_id;
+       u8 erp_id = mlxsw_sp_acl_erp_mask_erp_id(aentry->erp_mask);
+       struct mlxsw_sp_acl_tcam_region *region = aregion->region;
+       char ptce3_pl[MLXSW_REG_PTCE3_LEN];
+       u32 kvdl_index, priority;
+       int err;
+
+       err = mlxsw_sp_acl_tcam_priority_get(mlxsw_sp, rulei, &priority, true);
+       if (err)
+               return err;
+       kvdl_index = mlxsw_afa_block_first_kvdl_index(rulei->act_block);
+       mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_UPDATE,
+                            priority, region->tcam_region_info,
+                            aentry->ht_key.enc_key, erp_id,
+                            aentry->delta_info.start,
+                            aentry->delta_info.mask,
+                            aentry->delta_info.value,
+                            refcount_read(&lkey_id->refcnt) != 1, lkey_id->id,
+                            kvdl_index);
+       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl);
+}
+
+static int
 __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
                               struct mlxsw_sp_acl_atcam_region *aregion,
                               struct mlxsw_sp_acl_atcam_entry *aentry,
@@ -506,6 +534,16 @@ __mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp,
        mlxsw_sp_acl_erp_mask_put(aregion, aentry->erp_mask);
 }
 
+static int
+__mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                         struct mlxsw_sp_acl_atcam_region *aregion,
+                                         struct mlxsw_sp_acl_atcam_entry *aentry,
+                                         struct mlxsw_sp_acl_rule_info *rulei)
+{
+       return mlxsw_sp_acl_atcam_region_entry_action_replace(mlxsw_sp, aregion,
+                                                             aentry, rulei);
+}
+
 int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
                                 struct mlxsw_sp_acl_atcam_region *aregion,
                                 struct mlxsw_sp_acl_atcam_chunk *achunk,
@@ -542,6 +580,29 @@ void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp,
                __mlxsw_sp_acl_atcam_entry_del(mlxsw_sp, aregion, aentry);
 }
 
+int
+mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                       struct mlxsw_sp_acl_atcam_region *aregion,
+                                       struct mlxsw_sp_acl_atcam_chunk *achunk,
+                                       struct mlxsw_sp_acl_atcam_entry *aentry,
+                                       struct mlxsw_sp_acl_rule_info *rulei)
+{
+       int err;
+
+       if (mlxsw_sp_acl_atcam_is_centry(aentry))
+               err = mlxsw_sp_acl_ctcam_entry_action_replace(mlxsw_sp,
+                                                             &aregion->cregion,
+                                                             &achunk->cchunk,
+                                                             &aentry->centry,
+                                                             rulei);
+       else
+               err = __mlxsw_sp_acl_atcam_entry_action_replace(mlxsw_sp,
+                                                               aregion, aentry,
+                                                               rulei);
+
+       return err;
+}
+
 int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp,
                            struct mlxsw_sp_acl_atcam *atcam)
 {
index f3e834b..b0f2d8e 100644 (file)
@@ -89,6 +89,27 @@ mlxsw_sp_acl_ctcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp,
        cregion->ops->entry_remove(cregion, centry);
 }
 
+static int
+mlxsw_sp_acl_ctcam_region_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                              struct mlxsw_sp_acl_ctcam_region *cregion,
+                                              struct mlxsw_sp_acl_ctcam_entry *centry,
+                                              struct mlxsw_afa_block *afa_block,
+                                              unsigned int priority)
+{
+       char ptce2_pl[MLXSW_REG_PTCE2_LEN];
+       char *act_set;
+
+       mlxsw_reg_ptce2_pack(ptce2_pl, true, MLXSW_REG_PTCE2_OP_WRITE_UPDATE,
+                            cregion->region->tcam_region_info,
+                            centry->parman_item.index, priority);
+
+       act_set = mlxsw_afa_block_first_set(afa_block);
+       mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set);
+
+       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+}
+
+
 static int mlxsw_sp_acl_ctcam_region_parman_resize(void *priv,
                                                   unsigned long new_count)
 {
@@ -191,3 +212,15 @@ void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp,
        parman_item_remove(cregion->parman, &cchunk->parman_prio,
                           &centry->parman_item);
 }
+
+int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                           struct mlxsw_sp_acl_ctcam_region *cregion,
+                                           struct mlxsw_sp_acl_ctcam_chunk *cchunk,
+                                           struct mlxsw_sp_acl_ctcam_entry *centry,
+                                           struct mlxsw_sp_acl_rule_info *rulei)
+{
+       return mlxsw_sp_acl_ctcam_region_entry_action_replace(mlxsw_sp, cregion,
+                                                             centry,
+                                                             rulei->act_block,
+                                                             rulei->priority);
+}
index 015cf9a..f1f98a1 100644 (file)
@@ -779,6 +779,20 @@ static void mlxsw_sp_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
 }
 
 static int
+mlxsw_sp_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                      struct mlxsw_sp_acl_tcam_group *group,
+                                      struct mlxsw_sp_acl_tcam_entry *entry,
+                                      struct mlxsw_sp_acl_rule_info *rulei)
+{
+       const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+       struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk;
+       struct mlxsw_sp_acl_tcam_region *region = chunk->region;
+
+       return ops->entry_action_replace(mlxsw_sp, region->priv, chunk->priv,
+                                        entry->priv, rulei);
+}
+
+static int
 mlxsw_sp_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp,
                                     struct mlxsw_sp_acl_tcam_entry *entry,
                                     bool *activity)
@@ -939,6 +953,15 @@ mlxsw_sp_acl_tcam_flower_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv)
 }
 
 static int
+mlxsw_sp_acl_tcam_flower_rule_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                            void *ruleset_priv,
+                                            void *rule_priv,
+                                            struct mlxsw_sp_acl_rule_info *rulei)
+{
+       return -EOPNOTSUPP;
+}
+
+static int
 mlxsw_sp_acl_tcam_flower_rule_activity_get(struct mlxsw_sp *mlxsw_sp,
                                           void *rule_priv, bool *activity)
 {
@@ -958,6 +981,7 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = {
        .rule_priv_size         = mlxsw_sp_acl_tcam_flower_rule_priv_size,
        .rule_add               = mlxsw_sp_acl_tcam_flower_rule_add,
        .rule_del               = mlxsw_sp_acl_tcam_flower_rule_del,
+       .rule_action_replace    = mlxsw_sp_acl_tcam_flower_rule_action_replace,
        .rule_activity_get      = mlxsw_sp_acl_tcam_flower_rule_activity_get,
 };
 
@@ -1058,6 +1082,18 @@ mlxsw_sp_acl_tcam_mr_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv)
 }
 
 static int
+mlxsw_sp_acl_tcam_mr_rule_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                        void *ruleset_priv, void *rule_priv,
+                                        struct mlxsw_sp_acl_rule_info *rulei)
+{
+       struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
+       struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv;
+
+       return mlxsw_sp_acl_tcam_entry_action_replace(mlxsw_sp, &ruleset->group,
+                                                     &rule->entry, rulei);
+}
+
+static int
 mlxsw_sp_acl_tcam_mr_rule_activity_get(struct mlxsw_sp *mlxsw_sp,
                                       void *rule_priv, bool *activity)
 {
@@ -1077,6 +1113,7 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_mr_ops = {
        .rule_priv_size         = mlxsw_sp_acl_tcam_mr_rule_priv_size,
        .rule_add               = mlxsw_sp_acl_tcam_mr_rule_add,
        .rule_del               = mlxsw_sp_acl_tcam_mr_rule_del,
+       .rule_action_replace    = mlxsw_sp_acl_tcam_mr_rule_action_replace,
        .rule_activity_get      = mlxsw_sp_acl_tcam_mr_rule_activity_get,
 };
 
index 9a73759..95929b9 100644 (file)
@@ -48,6 +48,9 @@ struct mlxsw_sp_acl_profile_ops {
                        void *ruleset_priv, void *rule_priv,
                        struct mlxsw_sp_acl_rule_info *rulei);
        void (*rule_del)(struct mlxsw_sp *mlxsw_sp, void *rule_priv);
+       int (*rule_action_replace)(struct mlxsw_sp *mlxsw_sp,
+                                  void *ruleset_priv, void *rule_priv,
+                                  struct mlxsw_sp_acl_rule_info *rulei);
        int (*rule_activity_get)(struct mlxsw_sp *mlxsw_sp, void *rule_priv,
                                 bool *activity);
 };
@@ -121,6 +124,11 @@ void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp,
                                  struct mlxsw_sp_acl_ctcam_region *cregion,
                                  struct mlxsw_sp_acl_ctcam_chunk *cchunk,
                                  struct mlxsw_sp_acl_ctcam_entry *centry);
+int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                           struct mlxsw_sp_acl_ctcam_region *cregion,
+                                           struct mlxsw_sp_acl_ctcam_chunk *cchunk,
+                                           struct mlxsw_sp_acl_ctcam_entry *centry,
+                                           struct mlxsw_sp_acl_rule_info *rulei);
 static inline unsigned int
 mlxsw_sp_acl_ctcam_entry_offset(struct mlxsw_sp_acl_ctcam_entry *centry)
 {
@@ -212,6 +220,11 @@ void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp,
                                  struct mlxsw_sp_acl_atcam_region *aregion,
                                  struct mlxsw_sp_acl_atcam_chunk *achunk,
                                  struct mlxsw_sp_acl_atcam_entry *aentry);
+int mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
+                                           struct mlxsw_sp_acl_atcam_region *aregion,
+                                           struct mlxsw_sp_acl_atcam_chunk *achunk,
+                                           struct mlxsw_sp_acl_atcam_entry *aentry,
+                                           struct mlxsw_sp_acl_rule_info *rulei);
 int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp,
                            struct mlxsw_sp_acl_atcam *atcam);
 void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp,