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

Merge branch 'mlxsw-Add-support-for-mirror-action-with-flower'

Jiri Pirko says:

====================
mlxsw: Add support for mirror action with flower

Arkadi says:

Add support for mirror action with flower classifier. The first 3 patches
introduce a generic per-block resource infra. The last 4 patches add
support for flow based span.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 65b342f1 d0d13c18
...@@ -46,6 +46,12 @@ struct mlxsw_afa_ops { ...@@ -46,6 +46,12 @@ struct mlxsw_afa_ops {
void (*kvdl_set_del)(void *priv, u32 kvdl_index, bool is_first); void (*kvdl_set_del)(void *priv, u32 kvdl_index, bool is_first);
int (*kvdl_fwd_entry_add)(void *priv, u32 *p_kvdl_index, u8 local_port); int (*kvdl_fwd_entry_add)(void *priv, u32 *p_kvdl_index, u8 local_port);
void (*kvdl_fwd_entry_del)(void *priv, u32 kvdl_index); void (*kvdl_fwd_entry_del)(void *priv, u32 kvdl_index);
int (*counter_index_get)(void *priv, unsigned int *p_counter_index);
void (*counter_index_put)(void *priv, unsigned int counter_index);
int (*mirror_add)(void *priv, u8 locol_in_port, u8 local_out_port,
bool ingress, int *p_span_id);
void (*mirror_del)(void *priv, u8 locol_in_port, u8 local_out_port,
bool ingress);
}; };
struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set, struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set,
...@@ -63,12 +69,17 @@ int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block); ...@@ -63,12 +69,17 @@ int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block);
int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id); 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, int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
u16 trap_id); u16 trap_id);
int mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block,
u8 local_in_port, u8 local_out_port,
bool ingress);
int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block, int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block,
u8 local_port, bool in_port); u8 local_port, bool in_port);
int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block, int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
u16 vid, u8 pcp, u8 et); u16 vid, u8 pcp, u8 et);
int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block, int mlxsw_afa_block_append_allocated_counter(struct mlxsw_afa_block *block,
u32 counter_index); u32 counter_index);
int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
u32 *p_counter_index);
int mlxsw_afa_block_append_fid_set(struct mlxsw_afa_block *block, u16 fid); int mlxsw_afa_block_append_fid_set(struct mlxsw_afa_block *block, u16 fid);
int mlxsw_afa_block_append_mcrouter(struct mlxsw_afa_block *block, int mlxsw_afa_block_append_mcrouter(struct mlxsw_afa_block *block,
u16 expected_irif, u16 min_mtu, u16 expected_irif, u16 min_mtu,
......
...@@ -568,7 +568,7 @@ static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp, ...@@ -568,7 +568,7 @@ static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
span_entry->used = false; span_entry->used = false;
} }
static struct mlxsw_sp_span_entry * struct mlxsw_sp_span_entry *
mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port) mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port)
{ {
int i; int i;
...@@ -669,13 +669,28 @@ mlxsw_sp_span_entry_bound_port_find(struct mlxsw_sp_port *port, ...@@ -669,13 +669,28 @@ mlxsw_sp_span_entry_bound_port_find(struct mlxsw_sp_port *port,
static int static int
mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port, mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
struct mlxsw_sp_span_entry *span_entry, struct mlxsw_sp_span_entry *span_entry,
enum mlxsw_sp_span_type type) enum mlxsw_sp_span_type type,
bool bind)
{ {
struct mlxsw_sp_span_inspected_port *inspected_port;
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
char mpar_pl[MLXSW_REG_MPAR_LEN]; char mpar_pl[MLXSW_REG_MPAR_LEN];
char sbib_pl[MLXSW_REG_SBIB_LEN];
int pa_id = span_entry->id; int pa_id = span_entry->id;
/* bind the port to the SPAN entry */
mlxsw_reg_mpar_pack(mpar_pl, port->local_port,
(enum mlxsw_reg_mpar_i_e) type, bind, pa_id);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
}
static int
mlxsw_sp_span_inspected_port_add(struct mlxsw_sp_port *port,
struct mlxsw_sp_span_entry *span_entry,
enum mlxsw_sp_span_type type,
bool bind)
{
struct mlxsw_sp_span_inspected_port *inspected_port;
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
char sbib_pl[MLXSW_REG_SBIB_LEN];
int err; int err;
/* if it is an egress SPAN, bind a shared buffer to it */ /* if it is an egress SPAN, bind a shared buffer to it */
...@@ -691,12 +706,12 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port, ...@@ -691,12 +706,12 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
} }
} }
/* bind the port to the SPAN entry */ if (bind) {
mlxsw_reg_mpar_pack(mpar_pl, port->local_port, err = mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
(enum mlxsw_reg_mpar_i_e) type, true, pa_id); true);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
if (err) if (err)
goto err_mpar_reg_write; goto err_port_bind;
}
inspected_port = kzalloc(sizeof(*inspected_port), GFP_KERNEL); inspected_port = kzalloc(sizeof(*inspected_port), GFP_KERNEL);
if (!inspected_port) { if (!inspected_port) {
...@@ -709,8 +724,11 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port, ...@@ -709,8 +724,11 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
return 0; return 0;
err_mpar_reg_write:
err_inspected_port_alloc: err_inspected_port_alloc:
if (bind)
mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
false);
err_port_bind:
if (type == MLXSW_SP_SPAN_EGRESS) { if (type == MLXSW_SP_SPAN_EGRESS) {
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0); mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
...@@ -719,25 +737,22 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port, ...@@ -719,25 +737,22 @@ mlxsw_sp_span_inspected_port_bind(struct mlxsw_sp_port *port,
} }
static void static void
mlxsw_sp_span_inspected_port_unbind(struct mlxsw_sp_port *port, mlxsw_sp_span_inspected_port_del(struct mlxsw_sp_port *port,
struct mlxsw_sp_span_entry *span_entry, struct mlxsw_sp_span_entry *span_entry,
enum mlxsw_sp_span_type type) enum mlxsw_sp_span_type type,
bool bind)
{ {
struct mlxsw_sp_span_inspected_port *inspected_port; struct mlxsw_sp_span_inspected_port *inspected_port;
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
char mpar_pl[MLXSW_REG_MPAR_LEN];
char sbib_pl[MLXSW_REG_SBIB_LEN]; char sbib_pl[MLXSW_REG_SBIB_LEN];
int pa_id = span_entry->id;
inspected_port = mlxsw_sp_span_entry_bound_port_find(port, span_entry); inspected_port = mlxsw_sp_span_entry_bound_port_find(port, span_entry);
if (!inspected_port) if (!inspected_port)
return; return;
/* remove the inspected port */ if (bind)
mlxsw_reg_mpar_pack(mpar_pl, port->local_port, mlxsw_sp_span_inspected_port_bind(port, span_entry, type,
(enum mlxsw_reg_mpar_i_e) type, false, pa_id); false);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
/* remove the SBIB buffer if it was egress SPAN */ /* remove the SBIB buffer if it was egress SPAN */
if (type == MLXSW_SP_SPAN_EGRESS) { if (type == MLXSW_SP_SPAN_EGRESS) {
mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0); mlxsw_reg_sbib_pack(sbib_pl, port->local_port, 0);
...@@ -750,9 +765,9 @@ mlxsw_sp_span_inspected_port_unbind(struct mlxsw_sp_port *port, ...@@ -750,9 +765,9 @@ mlxsw_sp_span_inspected_port_unbind(struct mlxsw_sp_port *port,
kfree(inspected_port); kfree(inspected_port);
} }
static int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from, int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
struct mlxsw_sp_port *to, struct mlxsw_sp_port *to,
enum mlxsw_sp_span_type type) enum mlxsw_sp_span_type type, bool bind)
{ {
struct mlxsw_sp *mlxsw_sp = from->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = from->mlxsw_sp;
struct mlxsw_sp_span_entry *span_entry; struct mlxsw_sp_span_entry *span_entry;
...@@ -765,7 +780,7 @@ static int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from, ...@@ -765,7 +780,7 @@ static int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
netdev_dbg(from->dev, "Adding inspected port to SPAN entry %d\n", netdev_dbg(from->dev, "Adding inspected port to SPAN entry %d\n",
span_entry->id); span_entry->id);
err = mlxsw_sp_span_inspected_port_bind(from, span_entry, type); err = mlxsw_sp_span_inspected_port_add(from, span_entry, type, bind);
if (err) if (err)
goto err_port_bind; goto err_port_bind;
...@@ -776,9 +791,8 @@ static int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from, ...@@ -776,9 +791,8 @@ static int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
return err; return err;
} }
static void mlxsw_sp_span_mirror_remove(struct mlxsw_sp_port *from, void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, u8 destination_port,
u8 destination_port, enum mlxsw_sp_span_type type, bool bind)
enum mlxsw_sp_span_type type)
{ {
struct mlxsw_sp_span_entry *span_entry; struct mlxsw_sp_span_entry *span_entry;
...@@ -791,7 +805,7 @@ static void mlxsw_sp_span_mirror_remove(struct mlxsw_sp_port *from, ...@@ -791,7 +805,7 @@ static void mlxsw_sp_span_mirror_remove(struct mlxsw_sp_port *from,
netdev_dbg(from->dev, "removing inspected port from SPAN entry %d\n", netdev_dbg(from->dev, "removing inspected port from SPAN entry %d\n",
span_entry->id); span_entry->id);
mlxsw_sp_span_inspected_port_unbind(from, span_entry, type); mlxsw_sp_span_inspected_port_del(from, span_entry, type, bind);
} }
static int mlxsw_sp_port_sample_set(struct mlxsw_sp_port *mlxsw_sp_port, static int mlxsw_sp_port_sample_set(struct mlxsw_sp_port *mlxsw_sp_port,
...@@ -1582,7 +1596,8 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1582,7 +1596,8 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
mirror->to_local_port = to_port->local_port; mirror->to_local_port = to_port->local_port;
mirror->ingress = ingress; mirror->ingress = ingress;
span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS; span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_port, span_type); return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_port, span_type,
true);
} }
static void static void
...@@ -1593,8 +1608,8 @@ mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1593,8 +1608,8 @@ mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
span_type = mirror->ingress ? span_type = mirror->ingress ?
MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS; MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
mlxsw_sp_span_mirror_remove(mlxsw_sp_port, mirror->to_local_port, mlxsw_sp_span_mirror_del(mlxsw_sp_port, mirror->to_local_port,
span_type); span_type, true);
} }
static int static int
......
...@@ -396,6 +396,16 @@ struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev); ...@@ -396,6 +396,16 @@ struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev);
struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev); struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port); void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev); struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev);
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
struct mlxsw_sp_port *to,
enum mlxsw_sp_span_type type,
bool bind);
void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from,
u8 destination_port,
enum mlxsw_sp_span_type type,
bool bind);
struct mlxsw_sp_span_entry *
mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port);
/* spectrum_dcb.c */ /* spectrum_dcb.c */
#ifdef CONFIG_MLXSW_SPECTRUM_DCB #ifdef CONFIG_MLXSW_SPECTRUM_DCB
...@@ -457,7 +467,6 @@ struct mlxsw_sp_acl_rule_info { ...@@ -457,7 +467,6 @@ struct mlxsw_sp_acl_rule_info {
struct mlxsw_afk_element_values values; struct mlxsw_afk_element_values values;
struct mlxsw_afa_block *act_block; struct mlxsw_afa_block *act_block;
unsigned int counter_index; unsigned int counter_index;
bool counter_valid;
}; };
enum mlxsw_sp_acl_profile { enum mlxsw_sp_acl_profile {
...@@ -545,6 +554,10 @@ int mlxsw_sp_acl_rulei_act_jump(struct mlxsw_sp_acl_rule_info *rulei, ...@@ -545,6 +554,10 @@ int mlxsw_sp_acl_rulei_act_jump(struct mlxsw_sp_acl_rule_info *rulei,
u16 group_id); u16 group_id);
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei); 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_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, int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei, struct mlxsw_sp_acl_rule_info *rulei,
struct net_device *out_dev); struct net_device *out_dev);
......
...@@ -462,27 +462,6 @@ u16 mlxsw_sp_acl_ruleset_group_id(struct mlxsw_sp_acl_ruleset *ruleset) ...@@ -462,27 +462,6 @@ u16 mlxsw_sp_acl_ruleset_group_id(struct mlxsw_sp_acl_ruleset *ruleset)
return ops->ruleset_group_id(ruleset->priv); return ops->ruleset_group_id(ruleset->priv);
} }
static int
mlxsw_sp_acl_rulei_counter_alloc(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei)
{
int err;
err = mlxsw_sp_flow_counter_alloc(mlxsw_sp, &rulei->counter_index);
if (err)
return err;
rulei->counter_valid = true;
return 0;
}
static void
mlxsw_sp_acl_rulei_counter_free(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei)
{
rulei->counter_valid = false;
mlxsw_sp_flow_counter_free(mlxsw_sp, rulei->counter_index);
}
struct mlxsw_sp_acl_rule_info * struct mlxsw_sp_acl_rule_info *
mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl) mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl)
{ {
...@@ -587,6 +566,34 @@ int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp, ...@@ -587,6 +566,34 @@ int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
local_port, in_port); 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, int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei, struct mlxsw_sp_acl_rule_info *rulei,
u32 action, u16 vid, u16 proto, u8 prio) u32 action, u16 vid, u16 proto, u8 prio)
...@@ -619,7 +626,7 @@ int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp, ...@@ -619,7 +626,7 @@ int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei) struct mlxsw_sp_acl_rule_info *rulei)
{ {
return mlxsw_afa_block_append_counter(rulei->act_block, return mlxsw_afa_block_append_counter(rulei->act_block,
rulei->counter_index); &rulei->counter_index);
} }
int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp,
...@@ -653,13 +660,8 @@ mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp, ...@@ -653,13 +660,8 @@ mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp,
goto err_rulei_create; goto err_rulei_create;
} }
err = mlxsw_sp_acl_rulei_counter_alloc(mlxsw_sp, rule->rulei);
if (err)
goto err_counter_alloc;
return rule; return rule;
err_counter_alloc:
mlxsw_sp_acl_rulei_destroy(rule->rulei);
err_rulei_create: err_rulei_create:
kfree(rule); kfree(rule);
err_alloc: err_alloc:
...@@ -672,7 +674,6 @@ void mlxsw_sp_acl_rule_destroy(struct mlxsw_sp *mlxsw_sp, ...@@ -672,7 +674,6 @@ void mlxsw_sp_acl_rule_destroy(struct mlxsw_sp *mlxsw_sp,
{ {
struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset;
mlxsw_sp_acl_rulei_counter_free(mlxsw_sp, rule->rulei);
mlxsw_sp_acl_rulei_destroy(rule->rulei); mlxsw_sp_acl_rulei_destroy(rule->rulei);
kfree(rule); kfree(rule);
mlxsw_sp_acl_ruleset_ref_dec(mlxsw_sp, ruleset); mlxsw_sp_acl_ruleset_ref_dec(mlxsw_sp, ruleset);
......
...@@ -108,11 +108,77 @@ static void mlxsw_sp_act_kvdl_fwd_entry_del(void *priv, u32 kvdl_index) ...@@ -108,11 +108,77 @@ static void mlxsw_sp_act_kvdl_fwd_entry_del(void *priv, u32 kvdl_index)
mlxsw_sp_kvdl_free(mlxsw_sp, kvdl_index); mlxsw_sp_kvdl_free(mlxsw_sp, kvdl_index);
} }
static int
mlxsw_sp_act_counter_index_get(void *priv, unsigned int *p_counter_index)
{
struct mlxsw_sp *mlxsw_sp = priv;
return mlxsw_sp_flow_counter_alloc(mlxsw_sp, p_counter_index);
}
static void
mlxsw_sp_act_counter_index_put(void *priv, unsigned int counter_index)
{
struct mlxsw_sp *mlxsw_sp = priv;
mlxsw_sp_flow_counter_free(mlxsw_sp, counter_index);
}
static int
mlxsw_sp_act_mirror_add(void *priv, u8 local_in_port, u8 local_out_port,
bool ingress, int *p_span_id)
{
struct mlxsw_sp_port *in_port, *out_port;
struct mlxsw_sp_span_entry *span_entry;
struct mlxsw_sp *mlxsw_sp = priv;
enum mlxsw_sp_span_type type;
int err;
type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
out_port = mlxsw_sp->ports[local_out_port];
in_port = mlxsw_sp->ports[local_in_port];
err = mlxsw_sp_span_mirror_add(in_port, out_port, type, false);
if (err)
return err;
span_entry = mlxsw_sp_span_entry_find(mlxsw_sp, local_out_port);
if (!span_entry) {
err = -ENOENT;
goto err_span_entry_find;
}
*p_span_id = span_entry->id;
return 0;
err_span_entry_find:
mlxsw_sp_span_mirror_del(in_port, local_out_port, type, false);
return err;
}
static void
mlxsw_sp_act_mirror_del(void *priv, u8 local_in_port, u8 local_out_port,
bool ingress)
{
struct mlxsw_sp *mlxsw_sp = priv;
struct mlxsw_sp_port *in_port;
enum mlxsw_sp_span_type type;
type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
in_port = mlxsw_sp->ports[local_in_port];
mlxsw_sp_span_mirror_del(in_port, local_out_port, type, false);
}
static const struct mlxsw_afa_ops mlxsw_sp_act_afa_ops = { static const struct mlxsw_afa_ops mlxsw_sp_act_afa_ops = {
.kvdl_set_add = mlxsw_sp_act_kvdl_set_add, .kvdl_set_add = mlxsw_sp_act_kvdl_set_add,
.kvdl_set_del = mlxsw_sp_act_kvdl_set_del, .kvdl_set_del = mlxsw_sp_act_kvdl_set_del,
.kvdl_fwd_entry_add = mlxsw_sp_act_kvdl_fwd_entry_add, .kvdl_fwd_entry_add = mlxsw_sp_act_kvdl_fwd_entry_add,
.kvdl_fwd_entry_del = mlxsw_sp_act_kvdl_fwd_entry_del, .kvdl_fwd_entry_del = mlxsw_sp_act_kvdl_fwd_entry_del,
.counter_index_get = mlxsw_sp_act_counter_index_get,
.counter_index_put = mlxsw_sp_act_counter_index_put,
.mirror_add = mlxsw_sp_act_mirror_add,
.mirror_del = mlxsw_sp_act_mirror_del,
}; };
int mlxsw_sp_afa_init(struct mlxsw_sp *mlxsw_sp) int mlxsw_sp_afa_init(struct mlxsw_sp *mlxsw_sp)
......
...@@ -108,6 +108,13 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, ...@@ -108,6 +108,13 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
out_dev); out_dev);
if (err) if (err)
return 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)) { } else if (is_tcf_vlan(a)) {
u16 proto = be16_to_cpu(tcf_vlan_push_proto(a)); u16 proto = be16_to_cpu(tcf_vlan_push_proto(a));
u32 action = tcf_vlan_action(a); u32 action = tcf_vlan_action(a);
......
...@@ -243,7 +243,8 @@ mlxsw_sp_mr_tcam_afa_block_create(struct mlxsw_sp *mlxsw_sp, ...@@ -243,7 +243,8 @@ mlxsw_sp_mr_tcam_afa_block_create(struct mlxsw_sp *mlxsw_sp,
if (!afa_block) if (!afa_block)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
err = mlxsw_afa_block_append_counter(afa_block, counter_index); err = mlxsw_afa_block_append_allocated_counter(afa_block,
counter_index);
if (err) if (err)
goto err; goto err;
......
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