Skip to content

Commit

Permalink
mlxsw: spectrum_acl: Add support for mirror action
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Arkadi Sharshevsky authored and David S. Miller committed Jan 21, 2018
1 parent 7928756 commit d0d13c1
Showing 5 changed files with 126 additions and 3 deletions.
87 changes: 85 additions & 2 deletions drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
Original file line number Diff line number Diff line change
@@ -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
3 changes: 2 additions & 1 deletion drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
Original file line number Diff line number Diff line change
@@ -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,
4 changes: 4 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.h
Original file line number Diff line number Diff line change
@@ -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);
28 changes: 28 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
Original file line number Diff line number Diff line change
@@ -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)
7 changes: 7 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit d0d13c1

Please sign in to comment.