mirror of https://gitee.com/openkylin/linux.git
mlxsw: spectrum_acl: Add support for mirror action
Add support for mirror action. Only one mirror action can be set per rule. Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7928756cd0
commit
d0d13c1858
|
@ -834,8 +834,68 @@ int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
|
|||
}
|
||||
EXPORT_SYMBOL(mlxsw_afa_block_append_trap_and_forward);
|
||||
|
||||
int mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block,
|
||||
u8 mirror_agent)
|
||||
struct mlxsw_afa_mirror {
|
||||
struct mlxsw_afa_resource resource;
|
||||
int span_id;
|
||||
u8 local_in_port;
|
||||
u8 local_out_port;
|
||||
bool ingress;
|
||||
};
|
||||
|
||||
static void
|
||||
mlxsw_afa_mirror_destroy(struct mlxsw_afa_block *block,
|
||||
struct mlxsw_afa_mirror *mirror)
|
||||
{
|
||||
block->afa->ops->mirror_del(block->afa->ops_priv,
|
||||
mirror->local_in_port,
|
||||
mirror->local_out_port,
|
||||
mirror->ingress);
|
||||
kfree(mirror);
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_afa_mirror_destructor(struct mlxsw_afa_block *block,
|
||||
struct mlxsw_afa_resource *resource)
|
||||
{
|
||||
struct mlxsw_afa_mirror *mirror;
|
||||
|
||||
mirror = container_of(resource, struct mlxsw_afa_mirror, resource);
|
||||
mlxsw_afa_mirror_destroy(block, mirror);
|
||||
}
|
||||
|
||||
static struct mlxsw_afa_mirror *
|
||||
mlxsw_afa_mirror_create(struct mlxsw_afa_block *block,
|
||||
u8 local_in_port, u8 local_out_port,
|
||||
bool ingress)
|
||||
{
|
||||
struct mlxsw_afa_mirror *mirror;
|
||||
int err;
|
||||
|
||||
mirror = kzalloc(sizeof(*mirror), GFP_KERNEL);
|
||||
if (!mirror)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
err = block->afa->ops->mirror_add(block->afa->ops_priv,
|
||||
local_in_port, local_out_port,
|
||||
ingress, &mirror->span_id);
|
||||
if (err)
|
||||
goto err_mirror_add;
|
||||
|
||||
mirror->ingress = ingress;
|
||||
mirror->local_out_port = local_out_port;
|
||||
mirror->local_in_port = local_in_port;
|
||||
mirror->resource.destructor = mlxsw_afa_mirror_destructor;
|
||||
mlxsw_afa_resource_add(block, &mirror->resource);
|
||||
return mirror;
|
||||
|
||||
err_mirror_add:
|
||||
kfree(mirror);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_afa_block_append_allocated_mirror(struct mlxsw_afa_block *block,
|
||||
u8 mirror_agent)
|
||||
{
|
||||
char *act = mlxsw_afa_block_append_action(block,
|
||||
MLXSW_AFA_TRAPDISC_CODE,
|
||||
|
@ -847,6 +907,29 @@ int mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block,
|
|||
mlxsw_afa_trapdisc_mirror_pack(act, true, mirror_agent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block,
|
||||
u8 local_in_port, u8 local_out_port, bool ingress)
|
||||
{
|
||||
struct mlxsw_afa_mirror *mirror;
|
||||
int err;
|
||||
|
||||
mirror = mlxsw_afa_mirror_create(block, local_in_port, local_out_port,
|
||||
ingress);
|
||||
if (IS_ERR(mirror))
|
||||
return PTR_ERR(mirror);
|
||||
|
||||
err = mlxsw_afa_block_append_allocated_mirror(block, mirror->span_id);
|
||||
if (err)
|
||||
goto err_append_allocated_mirror;
|
||||
|
||||
return 0;
|
||||
|
||||
err_append_allocated_mirror:
|
||||
mlxsw_afa_mirror_destroy(block, mirror);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_afa_block_append_mirror);
|
||||
|
||||
/* Forwarding Action
|
||||
|
|
|
@ -70,7 +70,8 @@ int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id);
|
|||
int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
|
||||
u16 trap_id);
|
||||
int mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block,
|
||||
u8 mirror_agent);
|
||||
u8 local_in_port, u8 local_out_port,
|
||||
bool ingress);
|
||||
int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block,
|
||||
u8 local_port, bool in_port);
|
||||
int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
|
||||
|
|
|
@ -554,6 +554,10 @@ int mlxsw_sp_acl_rulei_act_jump(struct mlxsw_sp_acl_rule_info *rulei,
|
|||
u16 group_id);
|
||||
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei);
|
||||
int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei);
|
||||
int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_acl_rule_info *rulei,
|
||||
struct mlxsw_sp_acl_block *block,
|
||||
struct net_device *out_dev);
|
||||
int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_acl_rule_info *rulei,
|
||||
struct net_device *out_dev);
|
||||
|
|
|
@ -566,6 +566,34 @@ int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
|
|||
local_port, in_port);
|
||||
}
|
||||
|
||||
int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_acl_rule_info *rulei,
|
||||
struct mlxsw_sp_acl_block *block,
|
||||
struct net_device *out_dev)
|
||||
{
|
||||
struct mlxsw_sp_acl_block_binding *binding;
|
||||
struct mlxsw_sp_port *out_port;
|
||||
struct mlxsw_sp_port *in_port;
|
||||
|
||||
if (!list_is_singular(&block->binding_list))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
binding = list_first_entry(&block->binding_list,
|
||||
struct mlxsw_sp_acl_block_binding, list);
|
||||
in_port = binding->mlxsw_sp_port;
|
||||
if (!mlxsw_sp_port_dev_check(out_dev))
|
||||
return -EINVAL;
|
||||
|
||||
out_port = netdev_priv(out_dev);
|
||||
if (out_port->mlxsw_sp != mlxsw_sp)
|
||||
return -EINVAL;
|
||||
|
||||
return mlxsw_afa_block_append_mirror(rulei->act_block,
|
||||
in_port->local_port,
|
||||
out_port->local_port,
|
||||
binding->ingress);
|
||||
}
|
||||
|
||||
int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_acl_rule_info *rulei,
|
||||
u32 action, u16 vid, u16 proto, u8 prio)
|
||||
|
|
|
@ -108,6 +108,13 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
|
|||
out_dev);
|
||||
if (err)
|
||||
return err;
|
||||
} else if (is_tcf_mirred_egress_mirror(a)) {
|
||||
struct net_device *out_dev = tcf_mirred_dev(a);
|
||||
|
||||
err = mlxsw_sp_acl_rulei_act_mirror(mlxsw_sp, rulei,
|
||||
block, out_dev);
|
||||
if (err)
|
||||
return err;
|
||||
} else if (is_tcf_vlan(a)) {
|
||||
u16 proto = be16_to_cpu(tcf_vlan_push_proto(a));
|
||||
u32 action = tcf_vlan_action(a);
|
||||
|
|
Loading…
Reference in New Issue