Skip to content

Commit

Permalink
Merge branch 'dsa-fdb-isolation'
Browse files Browse the repository at this point in the history
Vladimir Oltean says:

====================
DSA FDB isolation

There are use cases which need FDB isolation between standalone ports
and bridged ports, as well as isolation between ports of different
bridges. Most of these use cases are a result of the fact that packets
can now be partially forwarded by the software bridge, so one port might
need to send a packet to the CPU but its FDB lookup will see that it can
forward it directly to a bridge port where that packet was autonomously
learned. So the source port will attempt to shortcircuit the CPU and
forward autonomously, which it can't due to the forwarding isolation we
have in place. So we will have packet drops instead of proper operation.

Additionally, before DSA can implement IFF_UNICAST_FLT for standalone
ports, we must have control over which database we install FDB entries
corresponding to port MAC addresses in. We don't want to hinder the
operation of the bridging layer.

DSA does not have a driver API that encourages FDB isolation, so this
needs to be created. The basis for this is a new struct dsa_db which
annotates each FDB and MDB entry with the database it belongs to.

The sja1105 and felix drivers are modified to observe the dsa_db
argument, and therefore, enforce the FDB isolation.

Compared to the previous RFC patch series from August:
https://patchwork.kernel.org/project/netdevbpf/cover/20210818120150.892647-1-vladimir.oltean@nxp.com/

what is different is that I stopped trying to make SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE
blocking, instead I'm making use of the fact that DSA waits for switchdev FDB work
items to finish before a port leaves the bridge. This is possible since:
https://patchwork.kernel.org/project/netdevbpf/patch/20211024171757.3753288-7-vladimir.oltean@nxp.com/

Additionally, v2 is also rebased over the DSA LAG FDB work.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
davem330 committed Feb 27, 2022
2 parents 1bb1c5b + 54c3198 commit b42a738
Show file tree
Hide file tree
Showing 31 changed files with 925 additions and 510 deletions.
27 changes: 27 additions & 0 deletions Documentation/networking/dsa/sja1105.rst
Expand Up @@ -293,6 +293,33 @@ of dropped frames, which is a sum of frames dropped due to timing violations,
lack of destination ports and MTU enforcement checks). Byte-level counters are
not available.

Limitations
===========

The SJA1105 switch family always performs VLAN processing. When configured as
VLAN-unaware, frames carry a different VLAN tag internally, depending on
whether the port is standalone or under a VLAN-unaware bridge.

The virtual link keys are always fixed at {MAC DA, VLAN ID, VLAN PCP}, but the
driver asks for the VLAN ID and VLAN PCP when the port is under a VLAN-aware
bridge. Otherwise, it fills in the VLAN ID and PCP automatically, based on
whether the port is standalone or in a VLAN-unaware bridge, and accepts only
"VLAN-unaware" tc-flower keys (MAC DA).

The existing tc-flower keys that are offloaded using virtual links are no
longer operational after one of the following happens:

- port was standalone and joins a bridge (VLAN-aware or VLAN-unaware)
- port is part of a bridge whose VLAN awareness state changes
- port was part of a bridge and becomes standalone
- port was standalone, but another port joins a VLAN-aware bridge and this
changes the global VLAN awareness state of the bridge

The driver cannot veto all these operations, and it cannot update/remove the
existing tc-flower filters either. So for proper operation, the tc-flower
filters should be installed only after the forwarding configuration of the port
has been made, and removed by user space before making any changes to it.

Device Tree bindings and board design
=====================================

Expand Down
14 changes: 9 additions & 5 deletions drivers/net/dsa/b53/b53_common.c
Expand Up @@ -1708,7 +1708,8 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
}

int b53_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct b53_device *priv = ds->priv;
int ret;
Expand All @@ -1728,7 +1729,8 @@ int b53_fdb_add(struct dsa_switch *ds, int port,
EXPORT_SYMBOL(b53_fdb_add);

int b53_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct b53_device *priv = ds->priv;
int ret;
Expand Down Expand Up @@ -1829,7 +1831,8 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
EXPORT_SYMBOL(b53_fdb_dump);

int b53_mdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb)
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
struct b53_device *priv = ds->priv;
int ret;
Expand All @@ -1849,7 +1852,8 @@ int b53_mdb_add(struct dsa_switch *ds, int port,
EXPORT_SYMBOL(b53_mdb_add);

int b53_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb)
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
struct b53_device *priv = ds->priv;
int ret;
Expand All @@ -1865,7 +1869,7 @@ int b53_mdb_del(struct dsa_switch *ds, int port,
EXPORT_SYMBOL(b53_mdb_del);

int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
bool *tx_fwd_offload)
bool *tx_fwd_offload, struct netlink_ext_ack *extack)
{
struct b53_device *dev = ds->priv;
s8 cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
Expand Down
14 changes: 9 additions & 5 deletions drivers/net/dsa/b53/b53_priv.h
Expand Up @@ -324,7 +324,7 @@ void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data);
int b53_get_sset_count(struct dsa_switch *ds, int port, int sset);
void b53_get_ethtool_phy_stats(struct dsa_switch *ds, int port, uint64_t *data);
int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
bool *tx_fwd_offload);
bool *tx_fwd_offload, struct netlink_ext_ack *extack);
void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge);
void b53_br_set_stp_state(struct dsa_switch *ds, int port, u8 state);
void b53_br_fast_age(struct dsa_switch *ds, int port);
Expand Down Expand Up @@ -359,15 +359,19 @@ int b53_vlan_add(struct dsa_switch *ds, int port,
int b53_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
int b53_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid);
const unsigned char *addr, u16 vid,
struct dsa_db db);
int b53_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid);
const unsigned char *addr, u16 vid,
struct dsa_db db);
int b53_fdb_dump(struct dsa_switch *ds, int port,
dsa_fdb_dump_cb_t *cb, void *data);
int b53_mdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db);
int b53_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db);
int b53_mirror_add(struct dsa_switch *ds, int port,
struct dsa_mall_mirror_tc_entry *mirror, bool ingress);
enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port,
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/dsa/dsa_loop.c
Expand Up @@ -168,7 +168,8 @@ static int dsa_loop_phy_write(struct dsa_switch *ds, int port,

static int dsa_loop_port_bridge_join(struct dsa_switch *ds, int port,
struct dsa_bridge bridge,
bool *tx_fwd_offload)
bool *tx_fwd_offload,
struct netlink_ext_ack *extack)
{
dev_dbg(ds->dev, "%s: port: %d, bridge: %s\n",
__func__, port, bridge.dev->name);
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/dsa/hirschmann/hellcreek.c
Expand Up @@ -675,7 +675,8 @@ static int hellcreek_bridge_flags(struct dsa_switch *ds, int port,

static int hellcreek_port_bridge_join(struct dsa_switch *ds, int port,
struct dsa_bridge bridge,
bool *tx_fwd_offload)
bool *tx_fwd_offload,
struct netlink_ext_ack *extack)
{
struct hellcreek *hellcreek = ds->priv;

Expand Down Expand Up @@ -827,7 +828,8 @@ static int hellcreek_fdb_get(struct hellcreek *hellcreek,
}

static int hellcreek_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct hellcreek_fdb_entry entry = { 0 };
struct hellcreek *hellcreek = ds->priv;
Expand Down Expand Up @@ -872,7 +874,8 @@ static int hellcreek_fdb_add(struct dsa_switch *ds, int port,
}

static int hellcreek_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct hellcreek_fdb_entry entry = { 0 };
struct hellcreek *hellcreek = ds->priv;
Expand Down
16 changes: 10 additions & 6 deletions drivers/net/dsa/lan9303-core.c
Expand Up @@ -1111,7 +1111,8 @@ static void lan9303_port_disable(struct dsa_switch *ds, int port)

static int lan9303_port_bridge_join(struct dsa_switch *ds, int port,
struct dsa_bridge bridge,
bool *tx_fwd_offload)
bool *tx_fwd_offload,
struct netlink_ext_ack *extack)
{
struct lan9303 *chip = ds->priv;

Expand Down Expand Up @@ -1188,7 +1189,8 @@ static void lan9303_port_fast_age(struct dsa_switch *ds, int port)
}

static int lan9303_port_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct lan9303 *chip = ds->priv;

Expand All @@ -1200,8 +1202,8 @@ static int lan9303_port_fdb_add(struct dsa_switch *ds, int port,
}

static int lan9303_port_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)

const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct lan9303 *chip = ds->priv;

Expand Down Expand Up @@ -1245,7 +1247,8 @@ static int lan9303_port_mdb_prepare(struct dsa_switch *ds, int port,
}

static int lan9303_port_mdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb)
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
struct lan9303 *chip = ds->priv;
int err;
Expand All @@ -1260,7 +1263,8 @@ static int lan9303_port_mdb_add(struct dsa_switch *ds, int port,
}

static int lan9303_port_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb)
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
struct lan9303 *chip = ds->priv;

Expand Down
9 changes: 6 additions & 3 deletions drivers/net/dsa/lantiq_gswip.c
Expand Up @@ -1152,7 +1152,8 @@ static int gswip_vlan_remove(struct gswip_priv *priv,

static int gswip_port_bridge_join(struct dsa_switch *ds, int port,
struct dsa_bridge bridge,
bool *tx_fwd_offload)
bool *tx_fwd_offload,
struct netlink_ext_ack *extack)
{
struct net_device *br = bridge.dev;
struct gswip_priv *priv = ds->priv;
Expand Down Expand Up @@ -1389,13 +1390,15 @@ static int gswip_port_fdb(struct dsa_switch *ds, int port,
}

static int gswip_port_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
return gswip_port_fdb(ds, port, addr, vid, true);
}

static int gswip_port_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
return gswip_port_fdb(ds, port, addr, vid, false);
}
Expand Down
12 changes: 8 additions & 4 deletions drivers/net/dsa/microchip/ksz9477.c
Expand Up @@ -640,7 +640,8 @@ static int ksz9477_port_vlan_del(struct dsa_switch *ds, int port,
}

static int ksz9477_port_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct ksz_device *dev = ds->priv;
u32 alu_table[4];
Expand Down Expand Up @@ -697,7 +698,8 @@ static int ksz9477_port_fdb_add(struct dsa_switch *ds, int port,
}

static int ksz9477_port_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct ksz_device *dev = ds->priv;
u32 alu_table[4];
Expand Down Expand Up @@ -839,7 +841,8 @@ static int ksz9477_port_fdb_dump(struct dsa_switch *ds, int port,
}

static int ksz9477_port_mdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb)
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
struct ksz_device *dev = ds->priv;
u32 static_table[4];
Expand Down Expand Up @@ -914,7 +917,8 @@ static int ksz9477_port_mdb_add(struct dsa_switch *ds, int port,
}

static int ksz9477_port_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb)
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
struct ksz_device *dev = ds->priv;
u32 static_table[4];
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/dsa/microchip/ksz_common.c
Expand Up @@ -217,7 +217,8 @@ EXPORT_SYMBOL_GPL(ksz_get_ethtool_stats);

int ksz_port_bridge_join(struct dsa_switch *ds, int port,
struct dsa_bridge bridge,
bool *tx_fwd_offload)
bool *tx_fwd_offload,
struct netlink_ext_ack *extack)
{
/* port_stp_state_set() will be called after to put the port in
* appropriate state so there is no need to do anything.
Expand Down Expand Up @@ -276,7 +277,8 @@ int ksz_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb,
EXPORT_SYMBOL_GPL(ksz_port_fdb_dump);

int ksz_port_mdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb)
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
struct ksz_device *dev = ds->priv;
struct alu_struct alu;
Expand Down Expand Up @@ -321,7 +323,8 @@ int ksz_port_mdb_add(struct dsa_switch *ds, int port,
EXPORT_SYMBOL_GPL(ksz_port_mdb_add);

int ksz_port_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb)
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
struct ksz_device *dev = ds->priv;
struct alu_struct alu;
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/dsa/microchip/ksz_common.h
Expand Up @@ -159,16 +159,19 @@ void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf);
int ksz_port_bridge_join(struct dsa_switch *ds, int port,
struct dsa_bridge bridge, bool *tx_fwd_offload);
struct dsa_bridge bridge, bool *tx_fwd_offload,
struct netlink_ext_ack *extack);
void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
struct dsa_bridge bridge);
void ksz_port_fast_age(struct dsa_switch *ds, int port);
int ksz_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb,
void *data);
int ksz_port_mdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db);
int ksz_port_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb);
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db);
int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);

/* Common register access functions */
Expand Down
15 changes: 10 additions & 5 deletions drivers/net/dsa/mt7530.c
Expand Up @@ -1186,7 +1186,8 @@ mt7530_port_bridge_flags(struct dsa_switch *ds, int port,

static int
mt7530_port_bridge_join(struct dsa_switch *ds, int port,
struct dsa_bridge bridge, bool *tx_fwd_offload)
struct dsa_bridge bridge, bool *tx_fwd_offload,
struct netlink_ext_ack *extack)
{
struct dsa_port *dp = dsa_to_port(ds, port), *other_dp;
u32 port_bitmap = BIT(MT7530_CPU_PORT);
Expand Down Expand Up @@ -1349,7 +1350,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,

static int
mt7530_port_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct mt7530_priv *priv = ds->priv;
int ret;
Expand All @@ -1365,7 +1367,8 @@ mt7530_port_fdb_add(struct dsa_switch *ds, int port,

static int
mt7530_port_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid)
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
struct mt7530_priv *priv = ds->priv;
int ret;
Expand Down Expand Up @@ -1416,7 +1419,8 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port,

static int
mt7530_port_mdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb)
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
struct mt7530_priv *priv = ds->priv;
const u8 *addr = mdb->addr;
Expand All @@ -1442,7 +1446,8 @@ mt7530_port_mdb_add(struct dsa_switch *ds, int port,

static int
mt7530_port_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb)
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
struct mt7530_priv *priv = ds->priv;
const u8 *addr = mdb->addr;
Expand Down

0 comments on commit b42a738

Please sign in to comment.