Commit c2693363 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: request drivers to perform FDB isolation

For DSA, to encourage drivers to perform FDB isolation simply means to
track which bridge does each FDB and MDB entry belong to. It then
becomes the driver responsibility to use something that makes the FDB
entry from one bridge not match the FDB lookup of ports from other
bridges.

The top-level functions where the bridge is determined are:
- dsa_port_fdb_{add,del}
- dsa_port_host_fdb_{add,del}
- dsa_port_mdb_{add,del}
- dsa_port_host_mdb_{add,del}

aka the pre-crosschip-notifier functions.

Changing the API to pass a reference to a bridge is not superfluous, and
looking at the passed bridge argument is not the same as having the
driver look at dsa_to_port(ds, port)->bridge from the ->port_fdb_add()
method.

DSA installs FDB and MDB entries on shared (CPU and DSA) ports as well,
and those do not have any dp->bridge information to retrieve, because
they are not in any bridge - they are merely the pipes that serve the
user ports that are in one or multiple bridges.

The struct dsa_bridge associated with each FDB/MDB entry is encapsulated
in a larger "struct dsa_db" database. Although only databases associated
to bridges are notified for now, this API will be the starting point for
implementing IFF_UNICAST_FLT in DSA. There, the idea is to install FDB
entries on the CPU port which belong to the corresponding user port's
port database. These are supposed to match only when the port is
standalone.

It is better to introduce the API in its expected final form than to
introduce it for bridges first, then to have to change drivers which may
have made one or more assumptions.

Drivers can use the provided bridge.num, but they can also use a
different numbering scheme that is more convenient.

DSA must perform refcounting on the CPU and DSA ports by also taking
into account the bridge number. So if two bridges request the same local
address, DSA must notify the driver twice, once for each bridge.

In fact, if the driver supports FDB isolation, DSA must perform
refcounting per bridge, but if the driver doesn't, DSA must refcount
host addresses across all bridges, otherwise it would be telling the
driver to delete an FDB entry for a bridge and the driver would delete
it for all bridges. So introduce a bool fdb_isolation in drivers which
would make all bridge databases passed to the cross-chip notifier have
the same number (0). This makes dsa_mac_addr_find() -> dsa_db_equal()
say that all bridge databases are the same database - which is
essentially the legacy behavior.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b6362bdf
...@@ -1708,7 +1708,8 @@ static int b53_arl_op(struct b53_device *dev, int op, int port, ...@@ -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, 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; struct b53_device *priv = ds->priv;
int ret; int ret;
...@@ -1728,7 +1729,8 @@ int b53_fdb_add(struct dsa_switch *ds, int port, ...@@ -1728,7 +1729,8 @@ int b53_fdb_add(struct dsa_switch *ds, int port,
EXPORT_SYMBOL(b53_fdb_add); EXPORT_SYMBOL(b53_fdb_add);
int b53_fdb_del(struct dsa_switch *ds, int port, 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; struct b53_device *priv = ds->priv;
int ret; int ret;
...@@ -1829,7 +1831,8 @@ int b53_fdb_dump(struct dsa_switch *ds, int port, ...@@ -1829,7 +1831,8 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
EXPORT_SYMBOL(b53_fdb_dump); EXPORT_SYMBOL(b53_fdb_dump);
int b53_mdb_add(struct dsa_switch *ds, int port, 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; struct b53_device *priv = ds->priv;
int ret; int ret;
...@@ -1849,7 +1852,8 @@ int b53_mdb_add(struct dsa_switch *ds, int port, ...@@ -1849,7 +1852,8 @@ int b53_mdb_add(struct dsa_switch *ds, int port,
EXPORT_SYMBOL(b53_mdb_add); EXPORT_SYMBOL(b53_mdb_add);
int b53_mdb_del(struct dsa_switch *ds, int port, 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; struct b53_device *priv = ds->priv;
int ret; int ret;
......
...@@ -359,15 +359,19 @@ int b53_vlan_add(struct dsa_switch *ds, int port, ...@@ -359,15 +359,19 @@ int b53_vlan_add(struct dsa_switch *ds, int port,
int b53_vlan_del(struct dsa_switch *ds, int port, int b53_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan); const struct switchdev_obj_port_vlan *vlan);
int b53_fdb_add(struct dsa_switch *ds, 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);
int b53_fdb_del(struct dsa_switch *ds, int port, 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, int b53_fdb_dump(struct dsa_switch *ds, int port,
dsa_fdb_dump_cb_t *cb, void *data); dsa_fdb_dump_cb_t *cb, void *data);
int b53_mdb_add(struct dsa_switch *ds, int port, 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, 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, int b53_mirror_add(struct dsa_switch *ds, int port,
struct dsa_mall_mirror_tc_entry *mirror, bool ingress); struct dsa_mall_mirror_tc_entry *mirror, bool ingress);
enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port, enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port,
......
...@@ -827,7 +827,8 @@ static int hellcreek_fdb_get(struct hellcreek *hellcreek, ...@@ -827,7 +827,8 @@ static int hellcreek_fdb_get(struct hellcreek *hellcreek,
} }
static int hellcreek_fdb_add(struct dsa_switch *ds, int port, 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_fdb_entry entry = { 0 };
struct hellcreek *hellcreek = ds->priv; struct hellcreek *hellcreek = ds->priv;
...@@ -872,7 +873,8 @@ static int hellcreek_fdb_add(struct dsa_switch *ds, int port, ...@@ -872,7 +873,8 @@ static int hellcreek_fdb_add(struct dsa_switch *ds, int port,
} }
static int hellcreek_fdb_del(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_fdb_entry entry = { 0 };
struct hellcreek *hellcreek = ds->priv; struct hellcreek *hellcreek = ds->priv;
......
...@@ -1188,7 +1188,8 @@ static void lan9303_port_fast_age(struct dsa_switch *ds, int port) ...@@ -1188,7 +1188,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, 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; struct lan9303 *chip = ds->priv;
...@@ -1200,8 +1201,8 @@ static int lan9303_port_fdb_add(struct dsa_switch *ds, int port, ...@@ -1200,8 +1201,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, 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; struct lan9303 *chip = ds->priv;
...@@ -1245,7 +1246,8 @@ static int lan9303_port_mdb_prepare(struct dsa_switch *ds, int port, ...@@ -1245,7 +1246,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, 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; struct lan9303 *chip = ds->priv;
int err; int err;
...@@ -1260,7 +1262,8 @@ static int lan9303_port_mdb_add(struct dsa_switch *ds, int port, ...@@ -1260,7 +1262,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, 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; struct lan9303 *chip = ds->priv;
......
...@@ -1389,13 +1389,15 @@ static int gswip_port_fdb(struct dsa_switch *ds, int port, ...@@ -1389,13 +1389,15 @@ static int gswip_port_fdb(struct dsa_switch *ds, int port,
} }
static int gswip_port_fdb_add(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); return gswip_port_fdb(ds, port, addr, vid, true);
} }
static int gswip_port_fdb_del(struct dsa_switch *ds, int port, 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); return gswip_port_fdb(ds, port, addr, vid, false);
} }
......
...@@ -640,7 +640,8 @@ static int ksz9477_port_vlan_del(struct dsa_switch *ds, int port, ...@@ -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, 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; struct ksz_device *dev = ds->priv;
u32 alu_table[4]; u32 alu_table[4];
...@@ -697,7 +698,8 @@ static int ksz9477_port_fdb_add(struct dsa_switch *ds, int port, ...@@ -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, 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; struct ksz_device *dev = ds->priv;
u32 alu_table[4]; u32 alu_table[4];
...@@ -839,7 +841,8 @@ static int ksz9477_port_fdb_dump(struct dsa_switch *ds, int port, ...@@ -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, 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; struct ksz_device *dev = ds->priv;
u32 static_table[4]; u32 static_table[4];
...@@ -914,7 +917,8 @@ static int ksz9477_port_mdb_add(struct dsa_switch *ds, int port, ...@@ -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, 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; struct ksz_device *dev = ds->priv;
u32 static_table[4]; u32 static_table[4];
......
...@@ -276,7 +276,8 @@ int ksz_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb, ...@@ -276,7 +276,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); EXPORT_SYMBOL_GPL(ksz_port_fdb_dump);
int ksz_port_mdb_add(struct dsa_switch *ds, int port, 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 ksz_device *dev = ds->priv;
struct alu_struct alu; struct alu_struct alu;
...@@ -321,7 +322,8 @@ int ksz_port_mdb_add(struct dsa_switch *ds, int port, ...@@ -321,7 +322,8 @@ int ksz_port_mdb_add(struct dsa_switch *ds, int port,
EXPORT_SYMBOL_GPL(ksz_port_mdb_add); EXPORT_SYMBOL_GPL(ksz_port_mdb_add);
int ksz_port_mdb_del(struct dsa_switch *ds, int port, 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 ksz_device *dev = ds->priv;
struct alu_struct alu; struct alu_struct alu;
......
...@@ -166,9 +166,11 @@ void ksz_port_fast_age(struct dsa_switch *ds, int port); ...@@ -166,9 +166,11 @@ 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, int ksz_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb,
void *data); void *data);
int ksz_port_mdb_add(struct dsa_switch *ds, int port, 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, 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); int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
/* Common register access functions */ /* Common register access functions */
......
...@@ -1349,7 +1349,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port, ...@@ -1349,7 +1349,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
static int static int
mt7530_port_fdb_add(struct dsa_switch *ds, int port, 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; struct mt7530_priv *priv = ds->priv;
int ret; int ret;
...@@ -1365,7 +1366,8 @@ mt7530_port_fdb_add(struct dsa_switch *ds, int port, ...@@ -1365,7 +1366,8 @@ mt7530_port_fdb_add(struct dsa_switch *ds, int port,
static int static int
mt7530_port_fdb_del(struct dsa_switch *ds, int port, 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; struct mt7530_priv *priv = ds->priv;
int ret; int ret;
...@@ -1416,7 +1418,8 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port, ...@@ -1416,7 +1418,8 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
static int static int
mt7530_port_mdb_add(struct dsa_switch *ds, int port, 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; struct mt7530_priv *priv = ds->priv;
const u8 *addr = mdb->addr; const u8 *addr = mdb->addr;
...@@ -1442,7 +1445,8 @@ mt7530_port_mdb_add(struct dsa_switch *ds, int port, ...@@ -1442,7 +1445,8 @@ mt7530_port_mdb_add(struct dsa_switch *ds, int port,
static int static int
mt7530_port_mdb_del(struct dsa_switch *ds, int port, 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; struct mt7530_priv *priv = ds->priv;
const u8 *addr = mdb->addr; const u8 *addr = mdb->addr;
......
...@@ -2456,7 +2456,8 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, ...@@ -2456,7 +2456,8 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
} }
static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, static int mv88e6xxx_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 mv88e6xxx_chip *chip = ds->priv; struct mv88e6xxx_chip *chip = ds->priv;
int err; int err;
...@@ -2470,7 +2471,8 @@ static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, ...@@ -2470,7 +2471,8 @@ static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
} }
static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, static int mv88e6xxx_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 mv88e6xxx_chip *chip = ds->priv; struct mv88e6xxx_chip *chip = ds->priv;
int err; int err;
...@@ -6002,7 +6004,8 @@ static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds, int port, ...@@ -6002,7 +6004,8 @@ static int mv88e6xxx_change_tag_protocol(struct dsa_switch *ds, int port,
} }
static int mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port, static int mv88e6xxx_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 mv88e6xxx_chip *chip = ds->priv; struct mv88e6xxx_chip *chip = ds->priv;
int err; int err;
...@@ -6016,7 +6019,8 @@ static int mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port, ...@@ -6016,7 +6019,8 @@ static int mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port,
} }
static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port, static int mv88e6xxx_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 mv88e6xxx_chip *chip = ds->priv; struct mv88e6xxx_chip *chip = ds->priv;
int err; int err;
......
...@@ -592,7 +592,8 @@ static int felix_fdb_dump(struct dsa_switch *ds, int port, ...@@ -592,7 +592,8 @@ static int felix_fdb_dump(struct dsa_switch *ds, int port,
} }
static int felix_fdb_add(struct dsa_switch *ds, int port, static int felix_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 ocelot *ocelot = ds->priv; struct ocelot *ocelot = ds->priv;
...@@ -600,7 +601,8 @@ static int felix_fdb_add(struct dsa_switch *ds, int port, ...@@ -600,7 +601,8 @@ static int felix_fdb_add(struct dsa_switch *ds, int port,
} }
static int felix_fdb_del(struct dsa_switch *ds, int port, static int felix_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 ocelot *ocelot = ds->priv; struct ocelot *ocelot = ds->priv;
...@@ -608,7 +610,8 @@ static int felix_fdb_del(struct dsa_switch *ds, int port, ...@@ -608,7 +610,8 @@ static int felix_fdb_del(struct dsa_switch *ds, int port,
} }
static int felix_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag, static int felix_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag,
const unsigned char *addr, u16 vid) const unsigned char *addr, u16 vid,
struct dsa_db db)
{ {
struct ocelot *ocelot = ds->priv; struct ocelot *ocelot = ds->priv;
...@@ -616,7 +619,8 @@ static int felix_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag, ...@@ -616,7 +619,8 @@ static int felix_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag lag,
} }
static int felix_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag, static int felix_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag,
const unsigned char *addr, u16 vid) const unsigned char *addr, u16 vid,
struct dsa_db db)
{ {
struct ocelot *ocelot = ds->priv; struct ocelot *ocelot = ds->priv;
...@@ -624,7 +628,8 @@ static int felix_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag, ...@@ -624,7 +628,8 @@ static int felix_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag lag,
} }
static int felix_mdb_add(struct dsa_switch *ds, int port, static int felix_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 ocelot *ocelot = ds->priv; struct ocelot *ocelot = ds->priv;
...@@ -632,7 +637,8 @@ static int felix_mdb_add(struct dsa_switch *ds, int port, ...@@ -632,7 +637,8 @@ static int felix_mdb_add(struct dsa_switch *ds, int port,
} }
static int felix_mdb_del(struct dsa_switch *ds, int port, static int felix_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 ocelot *ocelot = ds->priv; struct ocelot *ocelot = ds->priv;
......
...@@ -2398,7 +2398,8 @@ qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr, ...@@ -2398,7 +2398,8 @@ qca8k_port_fdb_insert(struct qca8k_priv *priv, const u8 *addr,
static int static int
qca8k_port_fdb_add(struct dsa_switch *ds, int port, qca8k_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 qca8k_priv *priv = (struct qca8k_priv *)ds->priv; struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
u16 port_mask = BIT(port); u16 port_mask = BIT(port);
...@@ -2408,7 +2409,8 @@ qca8k_port_fdb_add(struct dsa_switch *ds, int port, ...@@ -2408,7 +2409,8 @@ qca8k_port_fdb_add(struct dsa_switch *ds, int port,
static int static int
qca8k_port_fdb_del(struct dsa_switch *ds, int port, qca8k_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 qca8k_priv *priv = (struct qca8k_priv *)ds->priv; struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
u16 port_mask = BIT(port); u16 port_mask = BIT(port);
...@@ -2445,7 +2447,8 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port, ...@@ -2445,7 +2447,8 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
static int static int
qca8k_port_mdb_add(struct dsa_switch *ds, int port, qca8k_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 qca8k_priv *priv = ds->priv; struct qca8k_priv *priv = ds->priv;
const u8 *addr = mdb->addr; const u8 *addr = mdb->addr;
...@@ -2456,7 +2459,8 @@ qca8k_port_mdb_add(struct dsa_switch *ds, int port, ...@@ -2456,7 +2459,8 @@ qca8k_port_mdb_add(struct dsa_switch *ds, int port,
static int static int
qca8k_port_mdb_del(struct dsa_switch *ds, int port, qca8k_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 qca8k_priv *priv = ds->priv; struct qca8k_priv *priv = ds->priv;
const u8 *addr = mdb->addr; const u8 *addr = mdb->addr;
......
...@@ -1803,7 +1803,8 @@ int sja1105pqrs_fdb_del(struct dsa_switch *ds, int port, ...@@ -1803,7 +1803,8 @@ int sja1105pqrs_fdb_del(struct dsa_switch *ds, int port,
} }
static int sja1105_fdb_add(struct dsa_switch *ds, int port, static int sja1105_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 sja1105_private *priv = ds->priv; struct sja1105_private *priv = ds->priv;
...@@ -1811,7 +1812,8 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port, ...@@ -1811,7 +1812,8 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
} }
static int sja1105_fdb_del(struct dsa_switch *ds, int port, static int sja1105_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 sja1105_private *priv = ds->priv; struct sja1105_private *priv = ds->priv;
...@@ -1869,7 +1871,15 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port, ...@@ -1869,7 +1871,15 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
static void sja1105_fast_age(struct dsa_switch *ds, int port) static void sja1105_fast_age(struct dsa_switch *ds, int port)
{ {
struct dsa_port *dp = dsa_to_port(ds, port);
struct sja1105_private *priv = ds->priv; struct sja1105_private *priv = ds->priv;
struct dsa_db db = {
.type = DSA_DB_BRIDGE,
.bridge = {
.dev = dsa_port_bridge_dev_get(dp),
.num = dsa_port_bridge_num_get(dp),
},
};
int i; int i;
for (i = 0; i < SJA1105_MAX_L2_LOOKUP_COUNT; i++) { for (i = 0; i < SJA1105_MAX_L2_LOOKUP_COUNT; i++) {
...@@ -1897,7 +1907,7 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port) ...@@ -1897,7 +1907,7 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)
u64_to_ether_addr(l2_lookup.macaddr, macaddr); u64_to_ether_addr(l2_lookup.macaddr, macaddr);
rc = sja1105_fdb_del(ds, port, macaddr, l2_lookup.vlanid); rc = sja1105_fdb_del(ds, port, macaddr, l2_lookup.vlanid, db);
if (rc) { if (rc) {
dev_err(ds->dev, dev_err(ds->dev,
"Failed to delete FDB entry %pM vid %lld: %pe\n", "Failed to delete FDB entry %pM vid %lld: %pe\n",
...@@ -1908,15 +1918,17 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port) ...@@ -1908,15 +1918,17 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)
} }
static int sja1105_mdb_add(struct dsa_switch *ds, int port, static int sja1105_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)
{ {
return sja1105_fdb_add(ds, port, mdb->addr, mdb->vid); return sja1105_fdb_add(ds, port, mdb->addr, mdb->vid, db);
} }
static int sja1105_mdb_del(struct dsa_switch *ds, int port, static int sja1105_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)
{ {
return sja1105_fdb_del(ds, port, mdb->addr, mdb->vid); return sja1105_fdb_del(ds, port, mdb->addr, mdb->vid, db);
} }
/* Common function for unicast and broadcast flood configuration. /* Common function for unicast and broadcast flood configuration.
......
...@@ -341,11 +341,28 @@ struct dsa_link { ...@@ -341,11 +341,28 @@ struct dsa_link {
struct list_head list; struct list_head list;
}; };
enum dsa_db_type {
DSA_DB_PORT,
DSA_DB_LAG,
DSA_DB_BRIDGE,
};
struct dsa_db {
enum dsa_db_type type;
union {
const struct dsa_port *dp;
struct dsa_lag lag;
struct dsa_bridge bridge;
};
};
struct dsa_mac_addr { struct dsa_mac_addr {
unsigned char addr[ETH_ALEN]; unsigned char addr[ETH_ALEN];
u16 vid; u16 vid;
refcount_t refcount; refcount_t refcount;
struct list_head list; struct list_head list;
struct dsa_db db;
}; };
struct dsa_vlan { struct dsa_vlan {
...@@ -409,6 +426,13 @@ struct dsa_switch { ...@@ -409,6 +426,13 @@ struct dsa_switch {
*/ */
u32 mtu_enforcement_ingress:1; u32 mtu_enforcement_ingress:1;
/* Drivers that isolate the FDBs of multiple bridges must set this
* to true to receive the bridge as an argument in .port_fdb_{add,del}
* and .port_mdb_{add,del}. Otherwise, the bridge.num will always be
* passed as zero.
*/
u32 fdb_isolation:1;
/* Listener for switch fabric events */ /* Listener for switch fabric events */
struct notifier_block nb; struct notifier_block nb;
...@@ -941,23 +965,29 @@ struct dsa_switch_ops { ...@@ -941,23 +965,29 @@ struct dsa_switch_ops {
* Forwarding database * Forwarding database
*/ */
int (*port_fdb_add)(struct dsa_switch *ds, int port, int (*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);
int (*port_fdb_del)(struct dsa_switch *ds, int port, int (*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);
int (*port_fdb_dump)(struct dsa_switch *ds, int port, int (*port_fdb_dump)(struct dsa_switch *ds, int port,
dsa_fdb_dump_cb_t *cb, void *data); dsa_fdb_dump_cb_t *cb, void *data);
int (*lag_fdb_add)(struct dsa_switch *ds, struct dsa_lag lag, int (*lag_fdb_add)(struct dsa_switch *ds, struct dsa_lag lag,
const unsigned char *addr, u16 vid); const unsigned char *addr, u16 vid,
struct dsa_db db);
int (*lag_fdb_del)(struct dsa_switch *ds, struct dsa_lag lag, int (*lag_fdb_del)(struct dsa_switch *ds, struct dsa_lag lag,
const unsigned char *addr, u16 vid); const unsigned char *addr, u16 vid,
struct dsa_db db);
/* /*
* Multicast database * Multicast database
*/ */
int (*port_mdb_add)(struct dsa_switch *ds, int port, int (*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 (*port_mdb_del)(struct dsa_switch *ds, int port, int (*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);
/* /*
* RXNFC * RXNFC
*/ */
......
...@@ -67,6 +67,7 @@ struct dsa_notifier_fdb_info { ...@@ -67,6 +67,7 @@ struct dsa_notifier_fdb_info {
int port; int port;
const unsigned char *addr; const unsigned char *addr;
u16 vid; u16 vid;
struct dsa_db db;
}; };
/* DSA_NOTIFIER_LAG_FDB_* */ /* DSA_NOTIFIER_LAG_FDB_* */
...@@ -74,6 +75,7 @@ struct dsa_notifier_lag_fdb_info { ...@@ -74,6 +75,7 @@ struct dsa_notifier_lag_fdb_info {
struct dsa_lag *lag; struct dsa_lag *lag;
const unsigned char *addr; const unsigned char *addr;
u16 vid; u16 vid;
struct dsa_db db;
}; };
/* DSA_NOTIFIER_MDB_* */ /* DSA_NOTIFIER_MDB_* */
...@@ -81,6 +83,7 @@ struct dsa_notifier_mdb_info { ...@@ -81,6 +83,7 @@ struct dsa_notifier_mdb_info {
const struct switchdev_obj_port_mdb *mdb; const struct switchdev_obj_port_mdb *mdb;
int sw_index; int sw_index;
int port; int port;
struct dsa_db db;
}; };
/* DSA_NOTIFIER_LAG_* */ /* DSA_NOTIFIER_LAG_* */
......
...@@ -798,8 +798,19 @@ int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, ...@@ -798,8 +798,19 @@ int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
.port = dp->index, .port = dp->index,
.addr = addr, .addr = addr,
.vid = vid, .vid = vid,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
},
}; };
/* Refcounting takes bridge.num as a key, and should be global for all
* bridges in the absence of FDB isolation, and per bridge otherwise.
* Force the bridge.num to zero here in the absence of FDB isolation.
*/
if (!dp->ds->fdb_isolation)
info.db.bridge.num = 0;
return dsa_port_notify(dp, DSA_NOTIFIER_FDB_ADD, &info); return dsa_port_notify(dp, DSA_NOTIFIER_FDB_ADD, &info);
} }
...@@ -811,9 +822,15 @@ int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, ...@@ -811,9 +822,15 @@ int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
.port = dp->index, .port = dp->index,
.addr = addr, .addr = addr,
.vid = vid, .vid = vid,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
},
}; };
if (!dp->ds->fdb_isolation)
info.db.bridge.num = 0;
return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info); return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info);
} }
...@@ -825,6 +842,10 @@ int dsa_port_host_fdb_add(struct dsa_port *dp, const unsigned char *addr, ...@@ -825,6 +842,10 @@ int dsa_port_host_fdb_add(struct dsa_port *dp, const unsigned char *addr,
.port = dp->index, .port = dp->index,
.addr = addr, .addr = addr,
.vid = vid, .vid = vid,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
},
}; };
struct dsa_port *cpu_dp = dp->cpu_dp; struct dsa_port *cpu_dp = dp->cpu_dp;
int err; int err;
...@@ -839,6 +860,9 @@ int dsa_port_host_fdb_add(struct dsa_port *dp, const unsigned char *addr, ...@@ -839,6 +860,9 @@ int dsa_port_host_fdb_add(struct dsa_port *dp, const unsigned char *addr,
return err; return err;
} }
if (!dp->ds->fdb_isolation)
info.db.bridge.num = 0;
return dsa_port_notify(dp, DSA_NOTIFIER_HOST_FDB_ADD, &info); return dsa_port_notify(dp, DSA_NOTIFIER_HOST_FDB_ADD, &info);
} }
...@@ -850,6 +874,10 @@ int dsa_port_host_fdb_del(struct dsa_port *dp, const unsigned char *addr, ...@@ -850,6 +874,10 @@ int dsa_port_host_fdb_del(struct dsa_port *dp, const unsigned char *addr,
.port = dp->index, .port = dp->index,
.addr = addr, .addr = addr,
.vid = vid, .vid = vid,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
},
}; };
struct dsa_port *cpu_dp = dp->cpu_dp; struct dsa_port *cpu_dp = dp->cpu_dp;
int err; int err;
...@@ -860,6 +888,9 @@ int dsa_port_host_fdb_del(struct dsa_port *dp, const unsigned char *addr, ...@@ -860,6 +888,9 @@ int dsa_port_host_fdb_del(struct dsa_port *dp, const unsigned char *addr,
return err; return err;
} }
if (!dp->ds->fdb_isolation)
info.db.bridge.num = 0;
return dsa_port_notify(dp, DSA_NOTIFIER_HOST_FDB_DEL, &info); return dsa_port_notify(dp, DSA_NOTIFIER_HOST_FDB_DEL, &info);
} }
...@@ -870,8 +901,15 @@ int dsa_port_lag_fdb_add(struct dsa_port *dp, const unsigned char *addr, ...@@ -870,8 +901,15 @@ int dsa_port_lag_fdb_add(struct dsa_port *dp, const unsigned char *addr,
.lag = dp->lag, .lag = dp->lag,
.addr = addr, .addr = addr,
.vid = vid, .vid = vid,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
},
}; };
if (!dp->ds->fdb_isolation)
info.db.bridge.num = 0;
return dsa_port_notify(dp, DSA_NOTIFIER_LAG_FDB_ADD, &info); return dsa_port_notify(dp, DSA_NOTIFIER_LAG_FDB_ADD, &info);
} }
...@@ -882,8 +920,15 @@ int dsa_port_lag_fdb_del(struct dsa_port *dp, const unsigned char *addr, ...@@ -882,8 +920,15 @@ int dsa_port_lag_fdb_del(struct dsa_port *dp, const unsigned char *addr,
.lag = dp->lag, .lag = dp->lag,
.addr = addr, .addr = addr,
.vid = vid, .vid = vid,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
},
}; };
if (!dp->ds->fdb_isolation)
info.db.bridge.num = 0;
return dsa_port_notify(dp, DSA_NOTIFIER_LAG_FDB_DEL, &info); return dsa_port_notify(dp, DSA_NOTIFIER_LAG_FDB_DEL, &info);
} }
...@@ -905,8 +950,15 @@ int dsa_port_mdb_add(const struct dsa_port *dp, ...@@ -905,8 +950,15 @@ int dsa_port_mdb_add(const struct dsa_port *dp,
.sw_index = dp->ds->index, .sw_index = dp->ds->index,
.port = dp->index, .port = dp->index,
.mdb = mdb, .mdb = mdb,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
},
}; };
if (!dp->ds->fdb_isolation)
info.db.bridge.num = 0;
return dsa_port_notify(dp, DSA_NOTIFIER_MDB_ADD, &info); return dsa_port_notify(dp, DSA_NOTIFIER_MDB_ADD, &info);
} }
...@@ -917,8 +969,15 @@ int dsa_port_mdb_del(const struct dsa_port *dp, ...@@ -917,8 +969,15 @@ int dsa_port_mdb_del(const struct dsa_port *dp,
.sw_index = dp->ds->index, .sw_index = dp->ds->index,
.port = dp->index, .port = dp->index,
.mdb = mdb, .mdb = mdb,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
},
}; };
if (!dp->ds->fdb_isolation)
info.db.bridge.num = 0;
return dsa_port_notify(dp, DSA_NOTIFIER_MDB_DEL, &info); return dsa_port_notify(dp, DSA_NOTIFIER_MDB_DEL, &info);
} }
...@@ -929,6 +988,10 @@ int dsa_port_host_mdb_add(const struct dsa_port *dp, ...@@ -929,6 +988,10 @@ int dsa_port_host_mdb_add(const struct dsa_port *dp,
.sw_index = dp->ds->index, .sw_index = dp->ds->index,
.port = dp->index, .port = dp->index,
.mdb = mdb, .mdb = mdb,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
},
}; };
struct dsa_port *cpu_dp = dp->cpu_dp; struct dsa_port *cpu_dp = dp->cpu_dp;
int err; int err;
...@@ -937,6 +1000,9 @@ int dsa_port_host_mdb_add(const struct dsa_port *dp, ...@@ -937,6 +1000,9 @@ int dsa_port_host_mdb_add(const struct dsa_port *dp,
if (err) if (err)
return err; return err;
if (!dp->ds->fdb_isolation)
info.db.bridge.num = 0;
return dsa_port_notify(dp, DSA_NOTIFIER_HOST_MDB_ADD, &info); return dsa_port_notify(dp, DSA_NOTIFIER_HOST_MDB_ADD, &info);
} }
...@@ -947,6 +1013,10 @@ int dsa_port_host_mdb_del(const struct dsa_port *dp, ...@@ -947,6 +1013,10 @@ int dsa_port_host_mdb_del(const struct dsa_port *dp,
.sw_index = dp->ds->index, .sw_index = dp->ds->index,
.port = dp->index, .port = dp->index,
.mdb = mdb, .mdb = mdb,
.db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
},
}; };
struct dsa_port *cpu_dp = dp->cpu_dp; struct dsa_port *cpu_dp = dp->cpu_dp;
int err; int err;
...@@ -955,6 +1025,9 @@ int dsa_port_host_mdb_del(const struct dsa_port *dp, ...@@ -955,6 +1025,9 @@ int dsa_port_host_mdb_del(const struct dsa_port *dp,
if (err) if (err)
return err; return err;
if (!dp->ds->fdb_isolation)
info.db.bridge.num = 0;
return dsa_port_notify(dp, DSA_NOTIFIER_HOST_MDB_DEL, &info); return dsa_port_notify(dp, DSA_NOTIFIER_HOST_MDB_DEL, &info);
} }
......
This diff is collapsed.
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