]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
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 fa60c74a1659bba1d4d4a86690e8e2396c901306..edd397f42228a20d0af363b2b3de5af06a551745 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 2a9eac90002e18e2fa0fe60fd250c4d798713299..677526e5875032087438bc12fe54f75e9bd68a57 100644 (file)
@@ -192,6 +192,15 @@ static void mlxsw_sp1_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
                                     &chunk->cchunk, &entry->centry);
 }
 
+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,
@@ -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 62e6cf4bc16e74b8d14c018fccd577beb448e97a..234ab51916db9031ed4635e9dacf9bc7983e82a5 100644 (file)
@@ -210,6 +210,23 @@ static void mlxsw_sp2_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
                                     &entry->aentry);
 }
 
+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,
@@ -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 c4f9238591e6ef1c338a7434dfaa4f1701ea4106..44bbe7c9b68c032bc07de05ea3df8565559dd37e 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 e7bd8733e58e4bceb0ca0232856225df2ced6cd5..75f11c2d7b97d42882f9ff1732613a96a93998b9 100644 (file)
@@ -437,6 +437,34 @@ mlxsw_sp_acl_atcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp,
        aregion->ops->lkey_id_put(aregion, lkey_id);
 }
 
+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,
@@ -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 f3e834bfea1ab409c4c42f5694cf7c92bfd4aafe..b0f2d8e8ded0f3b5f8ee46f6459ab5080b320d3e 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 015cf9acf445232466753bf4423d4c03f45dbaba..f1f98a1770d2bd637c25bf59fe09b0caf888ef3c 100644 (file)
@@ -778,6 +778,20 @@ static void mlxsw_sp_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp,
        mlxsw_sp_acl_tcam_chunk_put(mlxsw_sp, chunk);
 }
 
+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,
@@ -938,6 +952,15 @@ mlxsw_sp_acl_tcam_flower_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv)
        mlxsw_sp_acl_tcam_entry_del(mlxsw_sp, &rule->entry);
 }
 
+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,
 };
 
@@ -1057,6 +1081,18 @@ mlxsw_sp_acl_tcam_mr_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv)
        mlxsw_sp_acl_tcam_entry_del(mlxsw_sp, &rule->entry);
 }
 
+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 9a73759d901f105baf983540ef86ee82bd5dde56..95929b9039eca5bece10b889ae0cc3f97863e53c 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,