net: dsa: mv88e6xxx: share the same default FDB
For hardware cross-chip bridging to work, user ports *and* DSA ports need to share a common address database, in order to switch a frame to the correct interconnected device. This is currently working for VLAN filtering aware systems, since Linux will implement a bridge group as a 802.1Q VLAN, which has its own FDB, including DSA and CPU links as members. However when the system doesn't support VLAN filtering, Linux only relies on the port-based VLAN to implement a bridge group. To fix hardware cross-chip bridging for such systems, set the same default address database 0 for user and DSA ports, instead of giving them all a different default database. Note that the bridging code prevents frames to egress between unbridged ports, and flushes FDB entries of a port when changing its STP state. Also note that the FID 0 is special and means "all" for ATU operations, but it's OK since it is used as a default forwarding address database. Fixes:2db9ce1fd9
("net: dsa: mv88e6xxx: assign default FDB to ports") Fixes:466dfa0770
("net: dsa: mv88e6xxx: assign dynamic FDB to bridges") Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
996ecb8246
commit
207afda1b5
|
@ -2181,27 +2181,10 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
|
||||||
struct net_device *bridge)
|
struct net_device *bridge)
|
||||||
{
|
{
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
u16 fid;
|
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
mutex_lock(&ps->smi_mutex);
|
mutex_lock(&ps->smi_mutex);
|
||||||
|
|
||||||
/* Get or create the bridge FID and assign it to the port */
|
|
||||||
for (i = 0; i < ps->num_ports; ++i)
|
|
||||||
if (ps->ports[i].bridge_dev == bridge)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (i < ps->num_ports)
|
|
||||||
err = _mv88e6xxx_port_fid_get(ds, i, &fid);
|
|
||||||
else
|
|
||||||
err = _mv88e6xxx_fid_new(ds, &fid);
|
|
||||||
if (err)
|
|
||||||
goto unlock;
|
|
||||||
|
|
||||||
err = _mv88e6xxx_port_fid_set(ds, port, fid);
|
|
||||||
if (err)
|
|
||||||
goto unlock;
|
|
||||||
|
|
||||||
/* Assign the bridge and remap each port's VLANTable */
|
/* Assign the bridge and remap each port's VLANTable */
|
||||||
ps->ports[port].bridge_dev = bridge;
|
ps->ports[port].bridge_dev = bridge;
|
||||||
|
|
||||||
|
@ -2213,7 +2196,6 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock:
|
|
||||||
mutex_unlock(&ps->smi_mutex);
|
mutex_unlock(&ps->smi_mutex);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -2223,16 +2205,10 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
|
||||||
{
|
{
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
struct net_device *bridge = ps->ports[port].bridge_dev;
|
struct net_device *bridge = ps->ports[port].bridge_dev;
|
||||||
u16 fid;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
mutex_lock(&ps->smi_mutex);
|
mutex_lock(&ps->smi_mutex);
|
||||||
|
|
||||||
/* Give the port a fresh Filtering Information Database */
|
|
||||||
if (_mv88e6xxx_fid_new(ds, &fid) ||
|
|
||||||
_mv88e6xxx_port_fid_set(ds, port, fid))
|
|
||||||
netdev_warn(ds->ports[port], "failed to assign a new FID\n");
|
|
||||||
|
|
||||||
/* Unassign the bridge and remap each port's VLANTable */
|
/* Unassign the bridge and remap each port's VLANTable */
|
||||||
ps->ports[port].bridge_dev = NULL;
|
ps->ports[port].bridge_dev = NULL;
|
||||||
|
|
||||||
|
@ -2558,11 +2534,11 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto abort;
|
goto abort;
|
||||||
|
|
||||||
/* Port based VLAN map: give each port its own address
|
/* Port based VLAN map: give each port the same default address
|
||||||
* database, and allow bidirectional communication between the
|
* database, and allow bidirectional communication between the
|
||||||
* CPU and DSA port(s), and the other ports.
|
* CPU and DSA port(s), and the other ports.
|
||||||
*/
|
*/
|
||||||
ret = _mv88e6xxx_port_fid_set(ds, port, port + 1);
|
ret = _mv88e6xxx_port_fid_set(ds, port, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto abort;
|
goto abort;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue