mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 20:46:48 +02:00
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 <petrm@mellanox.com> Reviewed-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7b2ef81fd2
commit
079c9f393b
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#define _MLXSW_CORE_ACL_FLEX_ACTIONS_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user