Previously, all VLANs (port-based or 802.1q) were sharing a single database in the ATU. This created problems in the case of a system where two ports/devices share a MAC address (e.g. Linksys WRT1900AC eth0/eth1).
This also clears any bootloader-set FDB defaults. This had caused issues creating port-based VLANs when mappings overlapped previous VLANs. Packets destined to a port not in the default port group flooded all ports. Tested on a 88E6171 (Linksys EA4500) and 88E6172 ('1900AC) Signed-off-by: Claudio Leite <leitec@staticky.com> Signed-off-by: Imre Kaloz <kaloz@openwrt.org> SVN-Revision: 46699
This commit is contained in:
parent
f57484c4af
commit
9cca6c5ad9
2 changed files with 19 additions and 4 deletions
|
@ -493,7 +493,7 @@ static int mvsw61xx_vtu_program(struct switch_dev *dev)
|
|||
sw16(dev, MV_GLOBALREG(VTU_VID),
|
||||
MV_VTU_VID_VALID | state->vlans[i].vid);
|
||||
sw16(dev, MV_GLOBALREG(VTU_SID), i);
|
||||
sw16(dev, MV_GLOBALREG(VTU_FID), 0);
|
||||
sw16(dev, MV_GLOBALREG(VTU_FID), i);
|
||||
sw16(dev, MV_GLOBALREG(VTU_DATA1), v1);
|
||||
sw16(dev, MV_GLOBALREG(VTU_DATA2), v2);
|
||||
sw16(dev, MV_GLOBALREG(VTU_DATA3), 0);
|
||||
|
@ -521,8 +521,10 @@ static void mvsw61xx_vlan_port_config(struct switch_dev *dev, int vno)
|
|||
if(mode != MV_VTUCTL_EGRESS_TAGGED)
|
||||
state->ports[i].pvid = state->vlans[vno].vid;
|
||||
|
||||
if (state->vlans[vno].port_based)
|
||||
if (state->vlans[vno].port_based) {
|
||||
state->ports[i].mask |= state->vlans[vno].mask;
|
||||
state->ports[i].fdb = vno;
|
||||
}
|
||||
else
|
||||
state->ports[i].qmode = MV_8021Q_MODE_SECURE;
|
||||
}
|
||||
|
@ -579,8 +581,14 @@ static int mvsw61xx_update_state(struct switch_dev *dev)
|
|||
|
||||
state->ports[i].mask &= ~(1 << i);
|
||||
|
||||
reg = sr16(dev, MV_PORTREG(VLANMAP, i)) & ~MV_PORTS_MASK;
|
||||
reg |= state->ports[i].mask;
|
||||
/* set default forwarding DB number and port mask */
|
||||
reg = sr16(dev, MV_PORTREG(CONTROL1, i)) & ~MV_FDB_HI_MASK;
|
||||
reg |= (state->ports[i].fdb >> MV_FDB_HI_SHIFT) &
|
||||
MV_FDB_HI_MASK;
|
||||
sw16(dev, MV_PORTREG(CONTROL1, i), reg);
|
||||
|
||||
reg = ((state->ports[i].fdb & 0xf) << MV_FDB_LO_SHIFT) |
|
||||
state->ports[i].mask;
|
||||
sw16(dev, MV_PORTREG(VLANMAP, i), reg);
|
||||
|
||||
reg = sr16(dev, MV_PORTREG(CONTROL2, i)) &
|
||||
|
@ -620,6 +628,7 @@ static int mvsw61xx_reset(struct switch_dev *dev)
|
|||
return -ETIMEDOUT;
|
||||
|
||||
for (i = 0; i < dev->ports; i++) {
|
||||
state->ports[i].fdb = 0;
|
||||
state->ports[i].qmode = 0;
|
||||
state->ports[i].mask = 0;
|
||||
state->ports[i].pvid = 0;
|
||||
|
|
|
@ -224,6 +224,11 @@ enum {
|
|||
|
||||
#define MV_PVID_MASK 0x0fff
|
||||
|
||||
#define MV_FDB_HI_MASK 0x00ff
|
||||
#define MV_FDB_LO_MASK 0xf000
|
||||
#define MV_FDB_HI_SHIFT 4
|
||||
#define MV_FDB_LO_SHIFT 12
|
||||
|
||||
struct mvsw61xx_state {
|
||||
struct switch_dev dev;
|
||||
struct mii_bus *bus;
|
||||
|
@ -238,6 +243,7 @@ struct mvsw61xx_state {
|
|||
|
||||
int vlan_enabled;
|
||||
struct port_state {
|
||||
u16 fdb;
|
||||
u16 pvid;
|
||||
u16 mask;
|
||||
u8 qmode;
|
||||
|
|
Loading…
Reference in a new issue