From 353def80c3d37a8e4a196b6856df4bc8c67304bf Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 23 Mar 2018 21:03:58 +0300 Subject: [PATCH] mlxsw: spectrum_span: Prevent duplicate mirrors In net commit 8175f7c4736f ("mlxsw: spectrum: Prevent duplicate mirrors") we prevented the user from mirroring more than once from a single binding point (port-direction pair). The fix was essentially reverted in a merge conflict resolution when net was merged into net-next. Restore it. Fixes: 03fe2debbb27 ("Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net") Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_span.c | 28 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c index ac24e52d74db..65a77708ff61 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c @@ -600,13 +600,17 @@ int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu) } static struct mlxsw_sp_span_inspected_port * -mlxsw_sp_span_entry_bound_port_find(struct mlxsw_sp_port *port, - struct mlxsw_sp_span_entry *span_entry) +mlxsw_sp_span_entry_bound_port_find(struct mlxsw_sp_span_entry *span_entry, + enum mlxsw_sp_span_type type, + struct mlxsw_sp_port *port, + bool bind) { struct mlxsw_sp_span_inspected_port *p; list_for_each_entry(p, &span_entry->bound_ports_list, list) - if (port->local_port == p->local_port) + if (type == p->type && + port->local_port == p->local_port && + bind == p->bound) return p; return NULL; } @@ -636,8 +640,22 @@ mlxsw_sp_span_inspected_port_add(struct mlxsw_sp_port *port, struct mlxsw_sp_span_inspected_port *inspected_port; struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp; char sbib_pl[MLXSW_REG_SBIB_LEN]; + int i; int err; + /* A given (source port, direction) can only be bound to one analyzer, + * so if a binding is requested, check for conflicts. + */ + if (bind) + for (i = 0; i < mlxsw_sp->span.entries_count; i++) { + struct mlxsw_sp_span_entry *curr = + &mlxsw_sp->span.entries[i]; + + if (mlxsw_sp_span_entry_bound_port_find(curr, type, + port, bind)) + return -EEXIST; + } + /* if it is an egress SPAN, bind a shared buffer to it */ if (type == MLXSW_SP_SPAN_EGRESS) { u32 buffsize = mlxsw_sp_span_mtu_to_buffsize(mlxsw_sp, @@ -665,6 +683,7 @@ mlxsw_sp_span_inspected_port_add(struct mlxsw_sp_port *port, } inspected_port->local_port = port->local_port; inspected_port->type = type; + inspected_port->bound = bind; list_add_tail(&inspected_port->list, &span_entry->bound_ports_list); return 0; @@ -691,7 +710,8 @@ mlxsw_sp_span_inspected_port_del(struct mlxsw_sp_port *port, struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp; char sbib_pl[MLXSW_REG_SBIB_LEN]; - inspected_port = mlxsw_sp_span_entry_bound_port_find(port, span_entry); + inspected_port = mlxsw_sp_span_entry_bound_port_find(span_entry, type, + port, bind); if (!inspected_port) return; -- 2.11.0