From 079c9f393b8d467995516c4716557373edefaa89 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Tue, 27 Feb 2018 14:53:44 +0100 Subject: [PATCH] mlxsw: spectrum: Keep mirror netdev in mlxsw_sp_span_entry Currently the only mirror action supported by mlxsw is mirror to another mlxsw physical port. Correspondingly, span_entry, which tracks each mlxsw mirror in the system, currently holds a u8 number of the destination port. To extend this system to mirror to gretap and ip6gretap netdevices, have struct mlxsw_sp_span_entry actually hold the destination netdevice itself. This change then trickles down in obvious manner to SPAN module API and mirror-related interfaces in struct mlxsw_afa_ops. To prevent use of invalid pointer, NETDEV_UNREGISTER needs to be hooked and the corresponding SPAN entry invalidated. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../mellanox/mlxsw/core_acl_flex_actions.c | 13 +++---- .../mellanox/mlxsw/core_acl_flex_actions.h | 7 +++- .../net/ethernet/mellanox/mlxsw/spectrum.c | 11 ++++-- .../ethernet/mellanox/mlxsw/spectrum_acl.c | 2 +- .../mlxsw/spectrum_acl_flex_actions.c | 8 ++-- .../ethernet/mellanox/mlxsw/spectrum_span.c | 39 ++++++++++++------- .../ethernet/mellanox/mlxsw/spectrum_span.h | 10 +++-- 7 files changed, 56 insertions(+), 34 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c index d1c2d85f396d..ba338428ffd1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c @@ -863,9 +863,8 @@ mlxsw_afa_mirror_destructor(struct mlxsw_afa_block *block, } static struct mlxsw_afa_mirror * -mlxsw_afa_mirror_create(struct mlxsw_afa_block *block, - u8 local_in_port, u8 local_out_port, - bool ingress) +mlxsw_afa_mirror_create(struct mlxsw_afa_block *block, u8 local_in_port, + const struct net_device *out_dev, bool ingress) { struct mlxsw_afa_mirror *mirror; int err; @@ -875,7 +874,7 @@ mlxsw_afa_mirror_create(struct mlxsw_afa_block *block, return ERR_PTR(-ENOMEM); err = block->afa->ops->mirror_add(block->afa->ops_priv, - local_in_port, local_out_port, + local_in_port, out_dev, ingress, &mirror->span_id); if (err) goto err_mirror_add; @@ -907,13 +906,13 @@ mlxsw_afa_block_append_allocated_mirror(struct mlxsw_afa_block *block, } int -mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block, - u8 local_in_port, u8 local_out_port, bool ingress) +mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block, u8 local_in_port, + const struct net_device *out_dev, bool ingress) { struct mlxsw_afa_mirror *mirror; int err; - mirror = mlxsw_afa_mirror_create(block, local_in_port, local_out_port, + mirror = mlxsw_afa_mirror_create(block, local_in_port, out_dev, ingress); if (IS_ERR(mirror)) return PTR_ERR(mirror); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h index 4e991ca6dce5..6dd601703c99 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h @@ -36,6 +36,7 @@ #define _MLXSW_CORE_ACL_FLEX_ACTIONS_H #include +#include struct mlxsw_afa; struct mlxsw_afa_block; @@ -48,7 +49,8 @@ struct mlxsw_afa_ops { 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, + int (*mirror_add)(void *priv, u8 local_in_port, + const struct net_device *out_dev, bool ingress, int *p_span_id); void (*mirror_del)(void *priv, u8 local_in_port, int span_id, bool ingress); @@ -70,7 +72,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 local_in_port, u8 local_out_port, + u8 local_in_port, + const struct net_device *out_dev, bool ingress); int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block, u8 local_port, bool in_port); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 10bb4891ec31..86991db3478c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1258,7 +1258,6 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress) { enum mlxsw_sp_span_type span_type; - struct mlxsw_sp_port *to_port; struct net_device *to_dev; to_dev = tcf_mirred_dev(a); @@ -1271,11 +1270,10 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port, netdev_err(mlxsw_sp_port->dev, "Cannot mirror to a non-spectrum port"); return -EOPNOTSUPP; } - to_port = netdev_priv(to_dev); mirror->ingress = ingress; 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_dev, span_type, true, &mirror->span_id); } @@ -4638,10 +4636,17 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct mlxsw_sp_span_entry *span_entry; struct mlxsw_sp *mlxsw_sp; int err = 0; mlxsw_sp = container_of(nb, struct mlxsw_sp, netdevice_nb); + if (event == NETDEV_UNREGISTER) { + span_entry = mlxsw_sp_span_entry_find_by_port(mlxsw_sp, dev); + if (span_entry) + mlxsw_sp_span_entry_invalidate(mlxsw_sp, span_entry); + } + if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev)) err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev, event, ptr); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 0897a5435cc2..50f5eacdfa24 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -590,7 +590,7 @@ int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp, return mlxsw_afa_block_append_mirror(rulei->act_block, in_port->local_port, - out_port->local_port, + out_dev, binding->ingress); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c index b450d3e4a905..510ce48d87f7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c @@ -126,18 +126,18 @@ mlxsw_sp_act_counter_index_put(void *priv, unsigned int counter_index) } static int -mlxsw_sp_act_mirror_add(void *priv, u8 local_in_port, u8 local_out_port, +mlxsw_sp_act_mirror_add(void *priv, u8 local_in_port, + const struct net_device *out_dev, bool ingress, int *p_span_id) { - struct mlxsw_sp_port *in_port, *out_port; + struct mlxsw_sp_port *in_port; struct mlxsw_sp *mlxsw_sp = priv; enum mlxsw_sp_span_type type; 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]; - return mlxsw_sp_span_mirror_add(in_port, out_port, type, + return mlxsw_sp_span_mirror_add(in_port, out_dev, type, false, p_span_id); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c index 442771908600..9819cdcf9e5c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c @@ -91,7 +91,8 @@ static void mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_span_entry *span_entry) { - u8 local_port = span_entry->local_port; + struct mlxsw_sp_port *to_port = netdev_priv(span_entry->to_dev); + u8 local_port = to_port->local_port; char mpat_pl[MLXSW_REG_MPAT_LEN]; int pa_id = span_entry->id; @@ -101,11 +102,12 @@ mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp *mlxsw_sp, } static struct mlxsw_sp_span_entry * -mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port) +mlxsw_sp_span_entry_create(struct mlxsw_sp *mlxsw_sp, + const struct net_device *to_dev) { + struct mlxsw_sp_port *to_port = netdev_priv(to_dev); struct mlxsw_sp_span_entry *span_entry = NULL; - struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp; - u8 local_port = port->local_port; + u8 local_port = to_port->local_port; int i; /* find a free entry to use */ @@ -122,30 +124,39 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port) return NULL; span_entry->ref_count = 1; - span_entry->local_port = local_port; + span_entry->to_dev = to_dev; return span_entry; } static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_span_entry *span_entry) { - mlxsw_sp_span_entry_deconfigure(mlxsw_sp, span_entry); + if (span_entry->to_dev) + mlxsw_sp_span_entry_deconfigure(mlxsw_sp, span_entry); } struct mlxsw_sp_span_entry * -mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp, u8 local_port) +mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp, + const struct net_device *to_dev) { int i; for (i = 0; i < mlxsw_sp->span.entries_count; i++) { struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i]; - if (curr->ref_count && curr->local_port == local_port) + if (curr->ref_count && curr->to_dev == to_dev) return curr; } return NULL; } +void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_span_entry *span_entry) +{ + mlxsw_sp_span_entry_deconfigure(mlxsw_sp, span_entry); + span_entry->to_dev = NULL; +} + static struct mlxsw_sp_span_entry * mlxsw_sp_span_entry_find_by_id(struct mlxsw_sp *mlxsw_sp, int span_id) { @@ -161,19 +172,19 @@ mlxsw_sp_span_entry_find_by_id(struct mlxsw_sp *mlxsw_sp, int span_id) } static struct mlxsw_sp_span_entry * -mlxsw_sp_span_entry_get(struct mlxsw_sp_port *port) +mlxsw_sp_span_entry_get(struct mlxsw_sp *mlxsw_sp, + const struct net_device *to_dev) { struct mlxsw_sp_span_entry *span_entry; - span_entry = mlxsw_sp_span_entry_find_by_port(port->mlxsw_sp, - port->local_port); + span_entry = mlxsw_sp_span_entry_find_by_port(mlxsw_sp, to_dev); if (span_entry) { /* Already exists, just take a reference */ span_entry->ref_count++; return span_entry; } - return mlxsw_sp_span_entry_create(port); + return mlxsw_sp_span_entry_create(mlxsw_sp, to_dev); } static int mlxsw_sp_span_entry_put(struct mlxsw_sp *mlxsw_sp, @@ -344,7 +355,7 @@ mlxsw_sp_span_inspected_port_del(struct mlxsw_sp_port *port, } int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from, - struct mlxsw_sp_port *to, + const struct net_device *to_dev, enum mlxsw_sp_span_type type, bool bind, int *p_span_id) { @@ -352,7 +363,7 @@ int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from, struct mlxsw_sp_span_entry *span_entry; int err; - span_entry = mlxsw_sp_span_entry_get(to); + span_entry = mlxsw_sp_span_entry_get(mlxsw_sp, to_dev); if (!span_entry) return -ENOENT; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h index 02dedf2fcd3f..44b307c59d0e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h @@ -51,7 +51,7 @@ struct mlxsw_sp_span_inspected_port { }; struct mlxsw_sp_span_entry { - u8 local_port; + const struct net_device *to_dev; struct list_head bound_ports_list; int ref_count; int id; @@ -61,13 +61,17 @@ int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from, - struct mlxsw_sp_port *to, + const struct net_device *to_dev, enum mlxsw_sp_span_type type, bool bind, int *p_span_id); void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id, enum mlxsw_sp_span_type type, bool bind); struct mlxsw_sp_span_entry * -mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp, u8 local_port); +mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp, + const struct net_device *to_dev); + +void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_span_entry *span_entry); int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu); -- 2.30.2