Commit 18346b70 authored by Jiri Pirko's avatar Jiri Pirko Committed by Jakub Kicinski

mlxsw: spectrum_matchall: Forbid to insert matchall rules in collision with flower rules

On ingress, the matchall rules doing mirroring and sampling are offloaded
into hardware blocks that are processed before any flower rules.
On egress, the matchall mirroring rules are offloaded into hardware
block that is processed after all flower rules.

Therefore check the priorities of inserted matchall rules against
existing flower rules and ensure the correct ordering.
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent aed65285
...@@ -894,7 +894,8 @@ extern const struct mlxsw_afk_ops mlxsw_sp1_afk_ops; ...@@ -894,7 +894,8 @@ extern const struct mlxsw_afk_ops mlxsw_sp1_afk_ops;
extern const struct mlxsw_afk_ops mlxsw_sp2_afk_ops; extern const struct mlxsw_afk_ops mlxsw_sp2_afk_ops;
/* spectrum_matchall.c */ /* spectrum_matchall.c */
int mlxsw_sp_mall_replace(struct mlxsw_sp_flow_block *block, int mlxsw_sp_mall_replace(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_flow_block *block,
struct tc_cls_matchall_offload *f); struct tc_cls_matchall_offload *f);
void mlxsw_sp_mall_destroy(struct mlxsw_sp_flow_block *block, void mlxsw_sp_mall_destroy(struct mlxsw_sp_flow_block *block,
struct tc_cls_matchall_offload *f); struct tc_cls_matchall_offload *f);
......
...@@ -135,9 +135,11 @@ static int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp, ...@@ -135,9 +135,11 @@ static int mlxsw_sp_flow_block_unbind(struct mlxsw_sp *mlxsw_sp,
static int mlxsw_sp_flow_block_mall_cb(struct mlxsw_sp_flow_block *flow_block, static int mlxsw_sp_flow_block_mall_cb(struct mlxsw_sp_flow_block *flow_block,
struct tc_cls_matchall_offload *f) struct tc_cls_matchall_offload *f)
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_flow_block_mlxsw_sp(flow_block);
switch (f->command) { switch (f->command) {
case TC_CLSMATCHALL_REPLACE: case TC_CLSMATCHALL_REPLACE:
return mlxsw_sp_mall_replace(flow_block, f); return mlxsw_sp_mall_replace(mlxsw_sp, flow_block, f);
case TC_CLSMATCHALL_DESTROY: case TC_CLSMATCHALL_DESTROY:
mlxsw_sp_mall_destroy(flow_block, f); mlxsw_sp_mall_destroy(flow_block, f);
return 0; return 0;
......
...@@ -192,13 +192,17 @@ static void mlxsw_sp_mall_prio_update(struct mlxsw_sp_flow_block *block) ...@@ -192,13 +192,17 @@ static void mlxsw_sp_mall_prio_update(struct mlxsw_sp_flow_block *block)
} }
} }
int mlxsw_sp_mall_replace(struct mlxsw_sp_flow_block *block, int mlxsw_sp_mall_replace(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_flow_block *block,
struct tc_cls_matchall_offload *f) struct tc_cls_matchall_offload *f)
{ {
struct mlxsw_sp_flow_block_binding *binding; struct mlxsw_sp_flow_block_binding *binding;
struct mlxsw_sp_mall_entry *mall_entry; struct mlxsw_sp_mall_entry *mall_entry;
__be16 protocol = f->common.protocol; __be16 protocol = f->common.protocol;
struct flow_action_entry *act; struct flow_action_entry *act;
unsigned int flower_min_prio;
unsigned int flower_max_prio;
bool flower_prio_valid;
int err; int err;
if (!flow_offload_has_one_action(&f->rule->action)) { if (!flow_offload_has_one_action(&f->rule->action)) {
...@@ -216,6 +220,19 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_flow_block *block, ...@@ -216,6 +220,19 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_flow_block *block,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
err = mlxsw_sp_flower_prio_get(mlxsw_sp, block, f->common.chain_index,
&flower_min_prio, &flower_max_prio);
if (err) {
if (err != -ENOENT) {
NL_SET_ERR_MSG(f->common.extack, "Failed to get flower priorities");
return err;
}
flower_prio_valid = false;
/* No flower filters are installed in specified chain. */
} else {
flower_prio_valid = true;
}
mall_entry = kzalloc(sizeof(*mall_entry), GFP_KERNEL); mall_entry = kzalloc(sizeof(*mall_entry), GFP_KERNEL);
if (!mall_entry) if (!mall_entry)
return -ENOMEM; return -ENOMEM;
...@@ -226,6 +243,18 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_flow_block *block, ...@@ -226,6 +243,18 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_flow_block *block,
act = &f->rule->action.entries[0]; act = &f->rule->action.entries[0];
if (act->id == FLOW_ACTION_MIRRED && protocol == htons(ETH_P_ALL)) { if (act->id == FLOW_ACTION_MIRRED && protocol == htons(ETH_P_ALL)) {
if (flower_prio_valid && mall_entry->ingress &&
mall_entry->priority >= flower_min_prio) {
NL_SET_ERR_MSG(f->common.extack, "Failed to add behind existing flower rules");
err = -EOPNOTSUPP;
goto errout;
}
if (flower_prio_valid && !mall_entry->ingress &&
mall_entry->priority <= flower_max_prio) {
NL_SET_ERR_MSG(f->common.extack, "Failed to add in front of existing flower rules");
err = -EOPNOTSUPP;
goto errout;
}
mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_MIRROR; mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_MIRROR;
mall_entry->mirror.to_dev = act->dev; mall_entry->mirror.to_dev = act->dev;
} else if (act->id == FLOW_ACTION_SAMPLE && } else if (act->id == FLOW_ACTION_SAMPLE &&
...@@ -235,6 +264,12 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_flow_block *block, ...@@ -235,6 +264,12 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp_flow_block *block,
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto errout; goto errout;
} }
if (flower_prio_valid &&
mall_entry->priority >= flower_min_prio) {
NL_SET_ERR_MSG(f->common.extack, "Failed to add behind existing flower rules");
err = -EOPNOTSUPP;
goto errout;
}
if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) { if (act->sample.rate > MLXSW_REG_MPSC_RATE_MAX) {
NL_SET_ERR_MSG(f->common.extack, "Sample rate not supported"); NL_SET_ERR_MSG(f->common.extack, "Sample rate not supported");
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment