Commit dda91bd7 authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-spectrum_acl-Forbid-unsupported-filters'

Ido Schimmel says:

====================
mlxsw: spectrum_acl: Forbid unsupported filters

Patches #1-#2 make mlxsw reject unsupported egress filters. These
include filters that match on VLAN and filters associated with a
redirect action. Patch #1 rejects such filters when they are configured
on egress and patch #2 rejects such filters when they are configured in
a shared block that user tries to bind to egress.

Patch #3 forbids matching on reserved TCP flags as this is not supported
by the current keys that mlxsw uses.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ca4ac168 7079676d
...@@ -1625,7 +1625,7 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1625,7 +1625,7 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
} }
flow_block_cb_incref(block_cb); flow_block_cb_incref(block_cb);
err = mlxsw_sp_acl_block_bind(mlxsw_sp, acl_block, err = mlxsw_sp_acl_block_bind(mlxsw_sp, acl_block,
mlxsw_sp_port, ingress); mlxsw_sp_port, ingress, f->extack);
if (err) if (err)
goto err_block_bind; goto err_block_bind;
......
...@@ -623,7 +623,8 @@ struct mlxsw_sp_acl_rule_info { ...@@ -623,7 +623,8 @@ struct mlxsw_sp_acl_rule_info {
unsigned int priority; unsigned int priority;
struct mlxsw_afk_element_values values; struct mlxsw_afk_element_values values;
struct mlxsw_afa_block *act_block; struct mlxsw_afa_block *act_block;
u8 action_created:1; u8 action_created:1,
egress_bind_blocker:1;
unsigned int counter_index; unsigned int counter_index;
}; };
...@@ -642,6 +643,7 @@ struct mlxsw_sp_acl_block { ...@@ -642,6 +643,7 @@ struct mlxsw_sp_acl_block {
struct mlxsw_sp *mlxsw_sp; struct mlxsw_sp *mlxsw_sp;
unsigned int rule_count; unsigned int rule_count;
unsigned int disable_count; unsigned int disable_count;
unsigned int egress_blocker_rule_count;
struct net *net; struct net *net;
}; };
...@@ -657,7 +659,8 @@ void mlxsw_sp_acl_block_destroy(struct mlxsw_sp_acl_block *block); ...@@ -657,7 +659,8 @@ void mlxsw_sp_acl_block_destroy(struct mlxsw_sp_acl_block *block);
int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_block *block, struct mlxsw_sp_acl_block *block,
struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp_port *mlxsw_sp_port,
bool ingress); bool ingress,
struct netlink_ext_ack *extack);
int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_block *block, struct mlxsw_sp_acl_block *block,
struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp_port *mlxsw_sp_port,
......
...@@ -239,7 +239,8 @@ mlxsw_sp_acl_block_lookup(struct mlxsw_sp_acl_block *block, ...@@ -239,7 +239,8 @@ mlxsw_sp_acl_block_lookup(struct mlxsw_sp_acl_block *block,
int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_block *block, struct mlxsw_sp_acl_block *block,
struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp_port *mlxsw_sp_port,
bool ingress) bool ingress,
struct netlink_ext_ack *extack)
{ {
struct mlxsw_sp_acl_block_binding *binding; struct mlxsw_sp_acl_block_binding *binding;
int err; int err;
...@@ -247,6 +248,11 @@ int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, ...@@ -247,6 +248,11 @@ int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp,
if (WARN_ON(mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress))) if (WARN_ON(mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress)))
return -EEXIST; return -EEXIST;
if (!ingress && block->egress_blocker_rule_count) {
NL_SET_ERR_MSG_MOD(extack, "Block cannot be bound to egress because it contains unsupported rules");
return -EOPNOTSUPP;
}
binding = kzalloc(sizeof(*binding), GFP_KERNEL); binding = kzalloc(sizeof(*binding), GFP_KERNEL);
if (!binding) if (!binding)
return -ENOMEM; return -ENOMEM;
...@@ -672,6 +678,7 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp, ...@@ -672,6 +678,7 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp,
{ {
struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
struct mlxsw_sp_acl_block *block = ruleset->ht_key.block;
int err; int err;
err = ops->rule_add(mlxsw_sp, ruleset->priv, rule->priv, rule->rulei); err = ops->rule_add(mlxsw_sp, ruleset->priv, rule->priv, rule->rulei);
...@@ -689,14 +696,14 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp, ...@@ -689,14 +696,14 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp,
* one, to be directly bound to device. The rest of the * one, to be directly bound to device. The rest of the
* rulesets are bound by "Goto action set". * rulesets are bound by "Goto action set".
*/ */
err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset, err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset, block);
ruleset->ht_key.block);
if (err) if (err)
goto err_ruleset_block_bind; goto err_ruleset_block_bind;
} }
list_add_tail(&rule->list, &mlxsw_sp->acl->rules); list_add_tail(&rule->list, &mlxsw_sp->acl->rules);
ruleset->ht_key.block->rule_count++; block->rule_count++;
block->egress_blocker_rule_count += rule->rulei->egress_bind_blocker;
return 0; return 0;
err_ruleset_block_bind: err_ruleset_block_bind:
...@@ -712,7 +719,9 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp, ...@@ -712,7 +719,9 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp,
{ {
struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
struct mlxsw_sp_acl_block *block = ruleset->ht_key.block;
block->egress_blocker_rule_count -= rule->rulei->egress_bind_blocker;
ruleset->ht_key.block->rule_count--; ruleset->ht_key.block->rule_count--;
list_del(&rule->list); list_del(&rule->list);
if (!ruleset->ht_key.chain_index && if (!ruleset->ht_key.chain_index &&
......
...@@ -78,6 +78,16 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, ...@@ -78,6 +78,16 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fid *fid; struct mlxsw_sp_fid *fid;
u16 fid_index; u16 fid_index;
if (mlxsw_sp_acl_block_is_egress_bound(block)) {
NL_SET_ERR_MSG_MOD(extack, "Redirect action is not supported on egress");
return -EOPNOTSUPP;
}
/* Forbid block with this rulei to be bound
* to egress in future.
*/
rulei->egress_bind_blocker = 1;
fid = mlxsw_sp_acl_dummy_fid(mlxsw_sp); fid = mlxsw_sp_acl_dummy_fid(mlxsw_sp);
fid_index = mlxsw_sp_fid_index(fid); fid_index = mlxsw_sp_fid_index(fid);
err = mlxsw_sp_acl_rulei_act_fid_set(mlxsw_sp, rulei, err = mlxsw_sp_acl_rulei_act_fid_set(mlxsw_sp, rulei,
...@@ -257,6 +267,12 @@ static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp, ...@@ -257,6 +267,12 @@ static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp,
flow_rule_match_tcp(rule, &match); flow_rule_match_tcp(rule, &match);
if (match.mask->flags & htons(0x0E00)) {
NL_SET_ERR_MSG_MOD(f->common.extack, "TCP flags match not supported on reserved bits");
dev_err(mlxsw_sp->bus_info->dev, "TCP flags match not supported on reserved bits\n");
return -EINVAL;
}
mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_TCP_FLAGS, mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_TCP_FLAGS,
ntohs(match.key->flags), ntohs(match.key->flags),
ntohs(match.mask->flags)); ntohs(match.mask->flags));
...@@ -390,6 +406,12 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, ...@@ -390,6 +406,12 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
NL_SET_ERR_MSG_MOD(f->common.extack, "vlan_id key is not supported on egress"); NL_SET_ERR_MSG_MOD(f->common.extack, "vlan_id key is not supported on egress");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
/* Forbid block with this rulei to be bound
* to egress in future.
*/
rulei->egress_bind_blocker = 1;
if (match.mask->vlan_id != 0) if (match.mask->vlan_id != 0)
mlxsw_sp_acl_rulei_keymask_u32(rulei, mlxsw_sp_acl_rulei_keymask_u32(rulei,
MLXSW_AFK_ELEMENT_VID, MLXSW_AFK_ELEMENT_VID,
......
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