Commit 803335ac authored by Petr Machata's avatar Petr Machata Committed by David S. Miller

mlxsw: Handle config changes pertinent to SPAN

For some netdevices, for which mlxsw offloads mirroring, may have a
complex relationship between the declared intent and low-level
device configuration.

Trying to accurately track which changes might influence offloading
decisions is finicky and error-prone. Instead, this patch introduces a
function mlxsw_sp_span_entry_respin, which re-queries the configuration
anew and, if different, removes the existing offloads and installs new
ones.

Call this function strategically at event handlers that might influence
the mirroring configuration.
Signed-off-by: default avatarPetr Machata <petrm@mellanox.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 169b5d95
/* /*
* drivers/net/ethernet/mellanox/mlxsw/spectrum.c * drivers/net/ethernet/mellanox/mlxsw/spectrum.c
* Copyright (c) 2015-2017 Mellanox Technologies. All rights reserved. * Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved.
* Copyright (c) 2015-2017 Jiri Pirko <jiri@mellanox.com> * Copyright (c) 2015-2017 Jiri Pirko <jiri@mellanox.com>
* Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com> * Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com>
* Copyright (c) 2015 Elad Raz <eladr@mellanox.com> * Copyright (c) 2015 Elad Raz <eladr@mellanox.com>
...@@ -3667,14 +3667,24 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, ...@@ -3667,14 +3667,24 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_afa_init; goto err_afa_init;
} }
err = mlxsw_sp_span_init(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to init span system\n");
goto err_span_init;
}
/* Initialize router after SPAN is initialized, so that the FIB and
* neighbor event handlers can issue SPAN respin.
*/
err = mlxsw_sp_router_init(mlxsw_sp); err = mlxsw_sp_router_init(mlxsw_sp);
if (err) { if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize router\n"); dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize router\n");
goto err_router_init; goto err_router_init;
} }
/* Initialize netdevice notifier after router is initialized, so that /* Initialize netdevice notifier after router and SPAN is initialized,
* the event handler can use router structures. * so that the event handler can use router structures and call SPAN
* respin.
*/ */
mlxsw_sp->netdevice_nb.notifier_call = mlxsw_sp_netdevice_event; mlxsw_sp->netdevice_nb.notifier_call = mlxsw_sp_netdevice_event;
err = register_netdevice_notifier(&mlxsw_sp->netdevice_nb); err = register_netdevice_notifier(&mlxsw_sp->netdevice_nb);
...@@ -3683,12 +3693,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, ...@@ -3683,12 +3693,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_netdev_notifier; goto err_netdev_notifier;
} }
err = mlxsw_sp_span_init(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to init span system\n");
goto err_span_init;
}
err = mlxsw_sp_acl_init(mlxsw_sp); err = mlxsw_sp_acl_init(mlxsw_sp);
if (err) { if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize ACL\n"); dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize ACL\n");
...@@ -3714,12 +3718,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, ...@@ -3714,12 +3718,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
err_dpipe_init: err_dpipe_init:
mlxsw_sp_acl_fini(mlxsw_sp); mlxsw_sp_acl_fini(mlxsw_sp);
err_acl_init: err_acl_init:
mlxsw_sp_span_fini(mlxsw_sp);
err_span_init:
unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb); unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb);
err_netdev_notifier: err_netdev_notifier:
mlxsw_sp_router_fini(mlxsw_sp); mlxsw_sp_router_fini(mlxsw_sp);
err_router_init: err_router_init:
mlxsw_sp_span_fini(mlxsw_sp);
err_span_init:
mlxsw_sp_afa_fini(mlxsw_sp); mlxsw_sp_afa_fini(mlxsw_sp);
err_afa_init: err_afa_init:
mlxsw_sp_counter_pool_fini(mlxsw_sp); mlxsw_sp_counter_pool_fini(mlxsw_sp);
...@@ -3745,9 +3749,9 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core) ...@@ -3745,9 +3749,9 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_ports_remove(mlxsw_sp); mlxsw_sp_ports_remove(mlxsw_sp);
mlxsw_sp_dpipe_fini(mlxsw_sp); mlxsw_sp_dpipe_fini(mlxsw_sp);
mlxsw_sp_acl_fini(mlxsw_sp); mlxsw_sp_acl_fini(mlxsw_sp);
mlxsw_sp_span_fini(mlxsw_sp);
unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb); unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb);
mlxsw_sp_router_fini(mlxsw_sp); mlxsw_sp_router_fini(mlxsw_sp);
mlxsw_sp_span_fini(mlxsw_sp);
mlxsw_sp_afa_fini(mlxsw_sp); mlxsw_sp_afa_fini(mlxsw_sp);
mlxsw_sp_counter_pool_fini(mlxsw_sp); mlxsw_sp_counter_pool_fini(mlxsw_sp);
mlxsw_sp_switchdev_fini(mlxsw_sp); mlxsw_sp_switchdev_fini(mlxsw_sp);
...@@ -4641,6 +4645,7 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb, ...@@ -4641,6 +4645,7 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
if (span_entry) if (span_entry)
mlxsw_sp_span_entry_invalidate(mlxsw_sp, span_entry); mlxsw_sp_span_entry_invalidate(mlxsw_sp, span_entry);
} }
mlxsw_sp_span_respin(mlxsw_sp);
if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev)) if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev))
err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev, err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev,
......
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
#include "spectrum_mr.h" #include "spectrum_mr.h"
#include "spectrum_mr_tcam.h" #include "spectrum_mr_tcam.h"
#include "spectrum_router.h" #include "spectrum_router.h"
#include "spectrum_span.h"
struct mlxsw_sp_fib; struct mlxsw_sp_fib;
struct mlxsw_sp_vr; struct mlxsw_sp_vr;
...@@ -2330,6 +2331,8 @@ static void mlxsw_sp_router_neigh_event_work(struct work_struct *work) ...@@ -2330,6 +2331,8 @@ static void mlxsw_sp_router_neigh_event_work(struct work_struct *work)
read_unlock_bh(&n->lock); read_unlock_bh(&n->lock);
rtnl_lock(); rtnl_lock();
mlxsw_sp_span_respin(mlxsw_sp);
entry_connected = nud_state & NUD_VALID && !dead; entry_connected = nud_state & NUD_VALID && !dead;
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n); neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
if (!entry_connected && !neigh_entry) if (!entry_connected && !neigh_entry)
...@@ -5589,6 +5592,8 @@ static void mlxsw_sp_router_fib4_event_work(struct work_struct *work) ...@@ -5589,6 +5592,8 @@ static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
/* Protect internal structures from changes */ /* Protect internal structures from changes */
rtnl_lock(); rtnl_lock();
mlxsw_sp_span_respin(mlxsw_sp);
switch (fib_work->event) { switch (fib_work->event) {
case FIB_EVENT_ENTRY_REPLACE: /* fall through */ case FIB_EVENT_ENTRY_REPLACE: /* fall through */
case FIB_EVENT_ENTRY_APPEND: /* fall through */ case FIB_EVENT_ENTRY_APPEND: /* fall through */
...@@ -5631,6 +5636,8 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work) ...@@ -5631,6 +5636,8 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
int err; int err;
rtnl_lock(); rtnl_lock();
mlxsw_sp_span_respin(mlxsw_sp);
switch (fib_work->event) { switch (fib_work->event) {
case FIB_EVENT_ENTRY_REPLACE: /* fall through */ case FIB_EVENT_ENTRY_REPLACE: /* fall through */
case FIB_EVENT_ENTRY_ADD: case FIB_EVENT_ENTRY_ADD:
......
...@@ -502,3 +502,27 @@ void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id, ...@@ -502,3 +502,27 @@ void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id,
span_entry->id); span_entry->id);
mlxsw_sp_span_inspected_port_del(from, span_entry, type, bind); mlxsw_sp_span_inspected_port_del(from, span_entry, type, bind);
} }
void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp)
{
int i;
int err;
ASSERT_RTNL();
for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
struct mlxsw_sp_span_parms sparms = {0};
if (!curr->ref_count)
continue;
err = curr->ops->parms(curr->to_dev, &sparms);
if (err)
continue;
if (memcmp(&sparms, &curr->parms, sizeof(sparms))) {
mlxsw_sp_span_entry_deconfigure(curr);
mlxsw_sp_span_entry_configure(mlxsw_sp, curr, sparms);
}
}
}
...@@ -76,6 +76,7 @@ struct mlxsw_sp_span_entry_ops { ...@@ -76,6 +76,7 @@ struct mlxsw_sp_span_entry_ops {
int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from, int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
const struct net_device *to_dev, const struct net_device *to_dev,
......
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