mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-14 17:55:42 +08:00
mlxsw: spectrum: Implement chain template hinting
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>
This commit is contained in:
parent
3473845273
commit
e2f2a1fd5b
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user