]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[linux.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum_acl.c
index 84a87d0593338845ef6d900d9ae865763729ead4..150b3a144b83e8c609a212867ed4870504f504eb 100644 (file)
@@ -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 &&