Commit 079c9f39 authored by Petr Machata's avatar Petr Machata Committed by David S. Miller

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: 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 7b2ef81f
...@@ -863,9 +863,8 @@ mlxsw_afa_mirror_destructor(struct mlxsw_afa_block *block, ...@@ -863,9 +863,8 @@ mlxsw_afa_mirror_destructor(struct mlxsw_afa_block *block,
} }
static struct mlxsw_afa_mirror * static struct mlxsw_afa_mirror *
mlxsw_afa_mirror_create(struct mlxsw_afa_block *block, mlxsw_afa_mirror_create(struct mlxsw_afa_block *block, u8 local_in_port,
u8 local_in_port, u8 local_out_port, const struct net_device *out_dev, bool ingress)
bool ingress)
{ {
struct mlxsw_afa_mirror *mirror; struct mlxsw_afa_mirror *mirror;
int err; int err;
...@@ -875,7 +874,7 @@ mlxsw_afa_mirror_create(struct mlxsw_afa_block *block, ...@@ -875,7 +874,7 @@ mlxsw_afa_mirror_create(struct mlxsw_afa_block *block,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
err = block->afa->ops->mirror_add(block->afa->ops_priv, 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); ingress, &mirror->span_id);
if (err) if (err)
goto err_mirror_add; goto err_mirror_add;
...@@ -907,13 +906,13 @@ mlxsw_afa_block_append_allocated_mirror(struct mlxsw_afa_block *block, ...@@ -907,13 +906,13 @@ mlxsw_afa_block_append_allocated_mirror(struct mlxsw_afa_block *block,
} }
int int
mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block, mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block, u8 local_in_port,
u8 local_in_port, u8 local_out_port, bool ingress) const struct net_device *out_dev, bool ingress)
{ {
struct mlxsw_afa_mirror *mirror; struct mlxsw_afa_mirror *mirror;
int err; 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); ingress);
if (IS_ERR(mirror)) if (IS_ERR(mirror))
return PTR_ERR(mirror); return PTR_ERR(mirror);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#define _MLXSW_CORE_ACL_FLEX_ACTIONS_H #define _MLXSW_CORE_ACL_FLEX_ACTIONS_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/netdevice.h>
struct mlxsw_afa; struct mlxsw_afa;
struct mlxsw_afa_block; struct mlxsw_afa_block;
...@@ -48,7 +49,8 @@ struct mlxsw_afa_ops { ...@@ -48,7 +49,8 @@ struct mlxsw_afa_ops {
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); int (*counter_index_get)(void *priv, unsigned int *p_counter_index);
void (*counter_index_put)(void *priv, unsigned int 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); bool ingress, int *p_span_id);
void (*mirror_del)(void *priv, u8 local_in_port, int span_id, void (*mirror_del)(void *priv, u8 local_in_port, int span_id,
bool ingress); bool ingress);
...@@ -70,7 +72,8 @@ int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id); ...@@ -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, 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, 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); 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);
......
...@@ -1258,7 +1258,6 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1258,7 +1258,6 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
bool ingress) bool ingress)
{ {
enum mlxsw_sp_span_type span_type; enum mlxsw_sp_span_type span_type;
struct mlxsw_sp_port *to_port;
struct net_device *to_dev; struct net_device *to_dev;
to_dev = tcf_mirred_dev(a); to_dev = tcf_mirred_dev(a);
...@@ -1271,11 +1270,10 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -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"); netdev_err(mlxsw_sp_port->dev, "Cannot mirror to a non-spectrum port");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
to_port = netdev_priv(to_dev);
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_dev, span_type,
true, &mirror->span_id); true, &mirror->span_id);
} }
...@@ -4638,10 +4636,17 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb, ...@@ -4638,10 +4636,17 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct mlxsw_sp_span_entry *span_entry;
struct mlxsw_sp *mlxsw_sp; struct mlxsw_sp *mlxsw_sp;
int err = 0; int err = 0;
mlxsw_sp = container_of(nb, struct mlxsw_sp, netdevice_nb); 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)) 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,
event, ptr); event, ptr);
......
...@@ -590,7 +590,7 @@ int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp, ...@@ -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, return mlxsw_afa_block_append_mirror(rulei->act_block,
in_port->local_port, in_port->local_port,
out_port->local_port, out_dev,
binding->ingress); binding->ingress);
} }
......
...@@ -126,18 +126,18 @@ mlxsw_sp_act_counter_index_put(void *priv, unsigned int counter_index) ...@@ -126,18 +126,18 @@ mlxsw_sp_act_counter_index_put(void *priv, unsigned int counter_index)
} }
static int 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) 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; struct mlxsw_sp *mlxsw_sp = priv;
enum mlxsw_sp_span_type type; enum mlxsw_sp_span_type type;
type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS; 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]; 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); false, p_span_id);
} }
......
...@@ -91,7 +91,8 @@ static void ...@@ -91,7 +91,8 @@ static void
mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_span_entry *span_entry) 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]; char mpat_pl[MLXSW_REG_MPAT_LEN];
int pa_id = span_entry->id; int pa_id = span_entry->id;
...@@ -101,11 +102,12 @@ mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp *mlxsw_sp, ...@@ -101,11 +102,12 @@ mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp *mlxsw_sp,
} }
static struct mlxsw_sp_span_entry * 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_span_entry *span_entry = NULL;
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp; u8 local_port = to_port->local_port;
u8 local_port = port->local_port;
int i; int i;
/* find a free entry to use */ /* find a free entry to use */
...@@ -122,30 +124,39 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port) ...@@ -122,30 +124,39 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port)
return NULL; return NULL;
span_entry->ref_count = 1; span_entry->ref_count = 1;
span_entry->local_port = local_port; span_entry->to_dev = to_dev;
return span_entry; return span_entry;
} }
static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_span_entry *span_entry) 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 * 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; int i;
for (i = 0; i < mlxsw_sp->span.entries_count; i++) { 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_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 curr;
} }
return NULL; 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 * static struct mlxsw_sp_span_entry *
mlxsw_sp_span_entry_find_by_id(struct mlxsw_sp *mlxsw_sp, int span_id) 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) ...@@ -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 * 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; struct mlxsw_sp_span_entry *span_entry;
span_entry = mlxsw_sp_span_entry_find_by_port(port->mlxsw_sp, span_entry = mlxsw_sp_span_entry_find_by_port(mlxsw_sp, to_dev);
port->local_port);
if (span_entry) { if (span_entry) {
/* Already exists, just take a reference */ /* Already exists, just take a reference */
span_entry->ref_count++; span_entry->ref_count++;
return span_entry; 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, 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, ...@@ -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, 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, enum mlxsw_sp_span_type type, bool bind,
int *p_span_id) int *p_span_id)
{ {
...@@ -352,7 +363,7 @@ int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from, ...@@ -352,7 +363,7 @@ int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
struct mlxsw_sp_span_entry *span_entry; struct mlxsw_sp_span_entry *span_entry;
int err; int err;
span_entry = mlxsw_sp_span_entry_get(to); span_entry = mlxsw_sp_span_entry_get(mlxsw_sp, to_dev);
if (!span_entry) if (!span_entry)
return -ENOENT; return -ENOENT;
......
...@@ -51,7 +51,7 @@ struct mlxsw_sp_span_inspected_port { ...@@ -51,7 +51,7 @@ struct mlxsw_sp_span_inspected_port {
}; };
struct mlxsw_sp_span_entry { struct mlxsw_sp_span_entry {
u8 local_port; const struct net_device *to_dev;
struct list_head bound_ports_list; struct list_head bound_ports_list;
int ref_count; int ref_count;
int id; int id;
...@@ -61,13 +61,17 @@ int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp); ...@@ -61,13 +61,17 @@ 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);
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, const struct net_device *to_dev,
enum mlxsw_sp_span_type type, enum mlxsw_sp_span_type type,
bool bind, int *p_span_id); bool bind, int *p_span_id);
void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id, void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id,
enum mlxsw_sp_span_type type, bool bind); enum mlxsw_sp_span_type type, bool bind);
struct 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);
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); int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu);
......
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