Skip to content

Commit

Permalink
Merge branch 'mlxsw-SPAN-Support-routes-pointing-at-bridges'
Browse files Browse the repository at this point in the history
Ido Schimmel says:

====================
mlxsw: SPAN: Support routes pointing at bridges

Petr says:

When mirroring to a gretap or ip6gretap netdevice, the route that
directs the encapsulated packets can reference a bridge. In that case,
in the software model, the packet is switched.

Thus when offloading mirroring like that, take into consideration FDB,
STP, PVID configured at the bridge, and whether that VLAN ID should be
tagged on egress.

Patch #1 introduces functions to get bridge PVID, VLAN flags and to look
up an FDB entry.

Patches #2 and #3 refactor some existing code and introduce a new
accessor function.

With patches #4 and #5 mlxsw calls mlxsw_sp_span_respin() on switchdev
events as well. There is no impact yet, because bridge as an underlay
device is still not allowed.

That is implemented in patch #6, which uses the new interfaces to figure
out on which one port the mirroring should be configured, and whether
the mirrored packets should be VLAN-tagged and how.

Changes from v2 to v3:

- Rename the suite of bridge accessor function to br_vlan_get_pvid(),
  br_vlan_get_info() and br_fdb_find_port(). The _get bit is to avoid
  clashing with an existing static function.

Changes from v1 to v2:

- Change the suite of bridge accessor functions to br_vlan_pvid_rtnl(),
  br_vlan_info_rtnl(), br_fdb_find_port_rtnl().
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 30, 2018
2 parents 6df9346 + 946a11e commit 8231bee
Show file tree
Hide file tree
Showing 10 changed files with 326 additions and 36 deletions.
50 changes: 25 additions & 25 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,29 +441,29 @@ static void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL);
}

int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
u8 state)
enum mlxsw_reg_spms_state mlxsw_sp_stp_spms_state(u8 state)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
enum mlxsw_reg_spms_state spms_state;
char *spms_pl;
int err;

switch (state) {
case BR_STATE_FORWARDING:
spms_state = MLXSW_REG_SPMS_STATE_FORWARDING;
break;
return MLXSW_REG_SPMS_STATE_FORWARDING;
case BR_STATE_LEARNING:
spms_state = MLXSW_REG_SPMS_STATE_LEARNING;
break;
return MLXSW_REG_SPMS_STATE_LEARNING;
case BR_STATE_LISTENING: /* fall-through */
case BR_STATE_DISABLED: /* fall-through */
case BR_STATE_BLOCKING:
spms_state = MLXSW_REG_SPMS_STATE_DISCARDING;
break;
return MLXSW_REG_SPMS_STATE_DISCARDING;
default:
BUG();
}
}

int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
u8 state)
{
enum mlxsw_reg_spms_state spms_state = mlxsw_sp_stp_spms_state(state);
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
char *spms_pl;
int err;

spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
if (!spms_pl)
Expand Down Expand Up @@ -3666,6 +3666,15 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_lag_init;
}

/* Initialize SPAN before router and switchdev, so that those components
* can call mlxsw_sp_span_respin().
*/
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_switchdev_init(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize switchdev\n");
Expand All @@ -3684,15 +3693,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
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);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize router\n");
Expand Down Expand Up @@ -3739,14 +3739,14 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
err_netdev_notifier:
mlxsw_sp_router_fini(mlxsw_sp);
err_router_init:
mlxsw_sp_span_fini(mlxsw_sp);
err_span_init:
mlxsw_sp_afa_fini(mlxsw_sp);
err_afa_init:
mlxsw_sp_counter_pool_fini(mlxsw_sp);
err_counter_pool_init:
mlxsw_sp_switchdev_fini(mlxsw_sp);
err_switchdev_init:
mlxsw_sp_span_fini(mlxsw_sp);
err_span_init:
mlxsw_sp_lag_fini(mlxsw_sp);
err_lag_init:
mlxsw_sp_buffers_fini(mlxsw_sp);
Expand All @@ -3768,10 +3768,10 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_acl_fini(mlxsw_sp);
unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb);
mlxsw_sp_router_fini(mlxsw_sp);
mlxsw_sp_span_fini(mlxsw_sp);
mlxsw_sp_afa_fini(mlxsw_sp);
mlxsw_sp_counter_pool_fini(mlxsw_sp);
mlxsw_sp_switchdev_fini(mlxsw_sp);
mlxsw_sp_span_fini(mlxsw_sp);
mlxsw_sp_lag_fini(mlxsw_sp);
mlxsw_sp_buffers_fini(mlxsw_sp);
mlxsw_sp_traps_fini(mlxsw_sp);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port,
enum mlxsw_reg_qeec_hr hr, u8 index,
u8 next_index, u32 maxrate);
enum mlxsw_reg_spms_state mlxsw_sp_stp_spms_state(u8 stp_state);
int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
u8 state);
int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable);
Expand Down
95 changes: 89 additions & 6 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,17 @@
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <linux/if_bridge.h>
#include <linux/list.h>
#include <net/arp.h>
#include <net/gre.h>
#include <net/ndisc.h>
#include <net/ip6_tunnel.h>

#include "spectrum.h"
#include "spectrum_span.h"
#include "spectrum_ipip.h"
#include "spectrum_span.h"
#include "spectrum_switchdev.h"

int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
{
Expand Down Expand Up @@ -167,6 +169,72 @@ mlxsw_sp_span_entry_unoffloadable(struct mlxsw_sp_span_parms *sparmsp)
return 0;
}

static struct net_device *
mlxsw_sp_span_entry_bridge_8021q(const struct net_device *br_dev,
unsigned char *dmac,
u16 *p_vid)
{
struct bridge_vlan_info vinfo;
struct net_device *edev;
u16 pvid;

if (WARN_ON(br_vlan_get_pvid(br_dev, &pvid)))
return NULL;
if (!pvid)
return NULL;

edev = br_fdb_find_port(br_dev, dmac, pvid);
if (!edev)
return NULL;

if (br_vlan_get_info(edev, pvid, &vinfo))
return NULL;
if (!(vinfo.flags & BRIDGE_VLAN_INFO_UNTAGGED))
*p_vid = pvid;
return edev;
}

static struct net_device *
mlxsw_sp_span_entry_bridge_8021d(const struct net_device *br_dev,
unsigned char *dmac)
{
return br_fdb_find_port(br_dev, dmac, 0);
}

static struct net_device *
mlxsw_sp_span_entry_bridge(const struct net_device *br_dev,
unsigned char dmac[ETH_ALEN],
u16 *p_vid)
{
struct mlxsw_sp_bridge_port *bridge_port;
enum mlxsw_reg_spms_state spms_state;
struct mlxsw_sp_port *port;
struct net_device *dev;
u8 stp_state;

if (br_vlan_enabled(br_dev))
dev = mlxsw_sp_span_entry_bridge_8021q(br_dev, dmac, p_vid);
else
dev = mlxsw_sp_span_entry_bridge_8021d(br_dev, dmac);
if (!dev)
return NULL;

port = mlxsw_sp_port_dev_lower_find(dev);
if (!port)
return NULL;

bridge_port = mlxsw_sp_bridge_port_find(port->mlxsw_sp->bridge, dev);
if (!bridge_port)
return NULL;

stp_state = mlxsw_sp_bridge_port_stp_state(bridge_port);
spms_state = mlxsw_sp_stp_spms_state(stp_state);
if (spms_state != MLXSW_REG_SPMS_STATE_FORWARDING)
return NULL;

return dev;
}

static __maybe_unused int
mlxsw_sp_span_entry_tunnel_parms_common(struct net_device *l3edev,
union mlxsw_sp_l3addr saddr,
Expand All @@ -177,21 +245,34 @@ mlxsw_sp_span_entry_tunnel_parms_common(struct net_device *l3edev,
struct mlxsw_sp_span_parms *sparmsp)
{
unsigned char dmac[ETH_ALEN];
u16 vid = 0;

if (mlxsw_sp_l3addr_is_zero(gw))
gw = daddr;

if (!l3edev || !mlxsw_sp_port_dev_check(l3edev) ||
mlxsw_sp_span_dmac(tbl, &gw, l3edev, dmac))
return mlxsw_sp_span_entry_unoffloadable(sparmsp);
if (!l3edev || mlxsw_sp_span_dmac(tbl, &gw, l3edev, dmac))
goto unoffloadable;

if (netif_is_bridge_master(l3edev)) {
l3edev = mlxsw_sp_span_entry_bridge(l3edev, dmac, &vid);
if (!l3edev)
goto unoffloadable;
}

if (!mlxsw_sp_port_dev_check(l3edev))
goto unoffloadable;

sparmsp->dest_port = netdev_priv(l3edev);
sparmsp->ttl = ttl;
memcpy(sparmsp->dmac, dmac, ETH_ALEN);
memcpy(sparmsp->smac, l3edev->dev_addr, ETH_ALEN);
sparmsp->saddr = saddr;
sparmsp->daddr = daddr;
sparmsp->vid = vid;
return 0;

unoffloadable:
return mlxsw_sp_span_entry_unoffloadable(sparmsp);
}

#if IS_ENABLED(CONFIG_NET_IPGRE)
Expand Down Expand Up @@ -268,9 +349,10 @@ mlxsw_sp_span_entry_gretap4_configure(struct mlxsw_sp_span_entry *span_entry,
/* Create a new port analayzer entry for local_port. */
mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
mlxsw_reg_mpat_eth_rspan_pack(mpat_pl, sparms.vid);
mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl,
MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER,
sparms.dmac, false);
sparms.dmac, !!sparms.vid);
mlxsw_reg_mpat_eth_rspan_l3_ipv4_pack(mpat_pl,
sparms.ttl, sparms.smac,
be32_to_cpu(sparms.saddr.addr4),
Expand Down Expand Up @@ -368,9 +450,10 @@ mlxsw_sp_span_entry_gretap6_configure(struct mlxsw_sp_span_entry *span_entry,
/* Create a new port analayzer entry for local_port. */
mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
mlxsw_reg_mpat_eth_rspan_pack(mpat_pl, sparms.vid);
mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl,
MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER,
sparms.dmac, false);
sparms.dmac, !!sparms.vid);
mlxsw_reg_mpat_eth_rspan_l3_ipv6_pack(mpat_pl, sparms.ttl, sparms.smac,
sparms.saddr.addr6,
sparms.daddr.addr6);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct mlxsw_sp_span_parms {
unsigned char smac[ETH_ALEN];
union mlxsw_sp_l3addr daddr;
union mlxsw_sp_l3addr saddr;
u16 vid;
};

struct mlxsw_sp_span_entry_ops;
Expand Down
Loading

0 comments on commit 8231bee

Please sign in to comment.