mlxsw: spectrum_acl: Add multicast router profile operations
Add specific ACL operations needed for programming multicast routing ACL groups and routes. 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>
This commit is contained in:
parent
add4550fca
commit
1a29d29394
|
@ -572,6 +572,7 @@ struct mlxsw_sp_acl_ruleset;
|
|||
/* spectrum_acl.c */
|
||||
enum mlxsw_sp_acl_profile {
|
||||
MLXSW_SP_ACL_PROFILE_FLOWER,
|
||||
MLXSW_SP_ACL_PROFILE_MR,
|
||||
};
|
||||
|
||||
struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl);
|
||||
|
|
|
@ -848,6 +848,15 @@ struct mlxsw_sp_acl_tcam_flower_rule {
|
|||
struct mlxsw_sp_acl_tcam_entry entry;
|
||||
};
|
||||
|
||||
struct mlxsw_sp_acl_tcam_mr_ruleset {
|
||||
struct mlxsw_sp_acl_tcam_chunk *chunk;
|
||||
struct mlxsw_sp_acl_tcam_group group;
|
||||
};
|
||||
|
||||
struct mlxsw_sp_acl_tcam_mr_rule {
|
||||
struct mlxsw_sp_acl_tcam_entry entry;
|
||||
};
|
||||
|
||||
static int
|
||||
mlxsw_sp_acl_tcam_flower_ruleset_add(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_acl_tcam *tcam,
|
||||
|
@ -952,9 +961,129 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = {
|
|||
.rule_activity_get = mlxsw_sp_acl_tcam_flower_rule_activity_get,
|
||||
};
|
||||
|
||||
static int
|
||||
mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_acl_tcam *tcam,
|
||||
void *ruleset_priv,
|
||||
struct mlxsw_afk_element_usage *tmplt_elusage)
|
||||
{
|
||||
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
|
||||
int err;
|
||||
|
||||
err = mlxsw_sp_acl_tcam_group_add(mlxsw_sp, tcam, &ruleset->group,
|
||||
mlxsw_sp_acl_tcam_patterns,
|
||||
MLXSW_SP_ACL_TCAM_PATTERNS_COUNT,
|
||||
tmplt_elusage);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* For most of the TCAM clients it would make sense to take a tcam chunk
|
||||
* only when the first rule is written. This is not the case for
|
||||
* multicast router as it is required to bind the multicast router to a
|
||||
* specific ACL Group ID which must exist in HW before multicast router
|
||||
* is initialized.
|
||||
*/
|
||||
ruleset->chunk = mlxsw_sp_acl_tcam_chunk_get(mlxsw_sp, &ruleset->group,
|
||||
1, tmplt_elusage);
|
||||
if (IS_ERR(ruleset->chunk)) {
|
||||
err = PTR_ERR(ruleset->chunk);
|
||||
goto err_chunk_get;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_chunk_get:
|
||||
mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_acl_tcam_mr_ruleset_del(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv)
|
||||
{
|
||||
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
|
||||
|
||||
mlxsw_sp_acl_tcam_chunk_put(mlxsw_sp, ruleset->chunk);
|
||||
mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_acl_tcam_mr_ruleset_bind(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
|
||||
struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
bool ingress)
|
||||
{
|
||||
/* Binding is done when initializing multicast router */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_acl_tcam_mr_ruleset_unbind(struct mlxsw_sp *mlxsw_sp,
|
||||
void *ruleset_priv,
|
||||
struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
bool ingress)
|
||||
{
|
||||
}
|
||||
|
||||
static u16
|
||||
mlxsw_sp_acl_tcam_mr_ruleset_group_id(void *ruleset_priv)
|
||||
{
|
||||
struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv;
|
||||
|
||||
return mlxsw_sp_acl_tcam_group_id(&ruleset->group);
|
||||
}
|
||||
|
||||
static size_t mlxsw_sp_acl_tcam_mr_rule_priv_size(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
return sizeof(struct mlxsw_sp_acl_tcam_mr_rule) +
|
||||
mlxsw_sp_acl_tcam_entry_priv_size(mlxsw_sp);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_acl_tcam_mr_rule_add(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_add(mlxsw_sp, &ruleset->group,
|
||||
&rule->entry, rulei);
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_acl_tcam_mr_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv)
|
||||
{
|
||||
struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv;
|
||||
|
||||
mlxsw_sp_acl_tcam_entry_del(mlxsw_sp, &rule->entry);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_acl_tcam_mr_rule_activity_get(struct mlxsw_sp *mlxsw_sp,
|
||||
void *rule_priv, bool *activity)
|
||||
{
|
||||
struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv;
|
||||
|
||||
return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, &rule->entry,
|
||||
activity);
|
||||
}
|
||||
|
||||
static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_mr_ops = {
|
||||
.ruleset_priv_size = sizeof(struct mlxsw_sp_acl_tcam_mr_ruleset),
|
||||
.ruleset_add = mlxsw_sp_acl_tcam_mr_ruleset_add,
|
||||
.ruleset_del = mlxsw_sp_acl_tcam_mr_ruleset_del,
|
||||
.ruleset_bind = mlxsw_sp_acl_tcam_mr_ruleset_bind,
|
||||
.ruleset_unbind = mlxsw_sp_acl_tcam_mr_ruleset_unbind,
|
||||
.ruleset_group_id = mlxsw_sp_acl_tcam_mr_ruleset_group_id,
|
||||
.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_activity_get = mlxsw_sp_acl_tcam_mr_rule_activity_get,
|
||||
};
|
||||
|
||||
static const struct mlxsw_sp_acl_profile_ops *
|
||||
mlxsw_sp_acl_tcam_profile_ops_arr[] = {
|
||||
[MLXSW_SP_ACL_PROFILE_FLOWER] = &mlxsw_sp_acl_tcam_flower_ops,
|
||||
[MLXSW_SP_ACL_PROFILE_MR] = &mlxsw_sp_acl_tcam_mr_ops,
|
||||
};
|
||||
|
||||
const struct mlxsw_sp_acl_profile_ops *
|
||||
|
|
Loading…
Reference in New Issue