mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 22:51:35 +00:00
mlxsw: spectrum_acl: Track rules that forbid egress block bind
Some matches and actions are not supported on egress. Track such rules and forbid a bind of block which contains them to egress. With this patch, the kernel tells the user he cannot do that: $ tc qdisc add dev ens16np1 ingress_block 22 clsact $ tc filter add block 22 protocol 802.1q pref 2 handle 101 flower vlan_id 100 skip_sw action pass $ tc qdisc add dev ens16np2 egress_block 22 clsact Error: mlxsw_spectrum: Block cannot be bound to egress because it contains unsupported rules. Signed-off-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
185556f092
commit
c9588e2812
@ -1625,7 +1625,7 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
}
|
||||
flow_block_cb_incref(block_cb);
|
||||
err = mlxsw_sp_acl_block_bind(mlxsw_sp, acl_block,
|
||||
mlxsw_sp_port, ingress);
|
||||
mlxsw_sp_port, ingress, f->extack);
|
||||
if (err)
|
||||
goto err_block_bind;
|
||||
|
||||
|
@ -623,7 +623,8 @@ struct mlxsw_sp_acl_rule_info {
|
||||
unsigned int priority;
|
||||
struct mlxsw_afk_element_values values;
|
||||
struct mlxsw_afa_block *act_block;
|
||||
u8 action_created:1;
|
||||
u8 action_created:1,
|
||||
egress_bind_blocker:1;
|
||||
unsigned int counter_index;
|
||||
};
|
||||
|
||||
@ -642,6 +643,7 @@ struct mlxsw_sp_acl_block {
|
||||
struct mlxsw_sp *mlxsw_sp;
|
||||
unsigned int rule_count;
|
||||
unsigned int disable_count;
|
||||
unsigned int egress_blocker_rule_count;
|
||||
struct net *net;
|
||||
};
|
||||
|
||||
@ -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,
|
||||
struct mlxsw_sp_acl_block *block,
|
||||
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,
|
||||
struct mlxsw_sp_acl_block *block,
|
||||
struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
|
@ -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,
|
||||
struct mlxsw_sp_acl_block *block,
|
||||
struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
bool ingress)
|
||||
bool ingress,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_sp_acl_block_binding *binding;
|
||||
int err;
|
||||
@ -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)))
|
||||
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);
|
||||
if (!binding)
|
||||
return -ENOMEM;
|
||||
@ -672,6 +678,7 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp,
|
||||
{
|
||||
struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
|
||||
const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops;
|
||||
struct mlxsw_sp_acl_block *block = ruleset->ht_key.block;
|
||||
int err;
|
||||
|
||||
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,
|
||||
* one, to be directly bound to device. The rest of the
|
||||
* rulesets are bound by "Goto action set".
|
||||
*/
|
||||
err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset,
|
||||
ruleset->ht_key.block);
|
||||
err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset, block);
|
||||
if (err)
|
||||
goto err_ruleset_block_bind;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
err_ruleset_block_bind:
|
||||
@ -712,7 +719,9 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp,
|
||||
{
|
||||
struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
|
||||
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--;
|
||||
list_del(&rule->list);
|
||||
if (!ruleset->ht_key.chain_index &&
|
||||
|
@ -83,6 +83,11 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
|
||||
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_index = mlxsw_sp_fid_index(fid);
|
||||
err = mlxsw_sp_acl_rulei_act_fid_set(mlxsw_sp, rulei,
|
||||
@ -395,6 +400,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");
|
||||
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)
|
||||
mlxsw_sp_acl_rulei_keymask_u32(rulei,
|
||||
MLXSW_AFK_ELEMENT_VID,
|
||||
|
Loading…
Reference in New Issue
Block a user