[OpenWrt-Devel] [PATCH 1/2] mvsw61xx: use unique forwarding database per VLAN

Claudio Leite leitec at staticky.com
Mon Jul 6 18:06:41 EDT 2015


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 at staticky.com>
---
The indentation looks broken (around HI/LO_SHIFT) but it's a
consequence of the diff '+' AFAICT.

 target/linux/generic/files/drivers/net/phy/mvsw61xx.c | 17 +++++++++++++----
 target/linux/generic/files/drivers/net/phy/mvsw61xx.h |  6 ++++++
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/target/linux/generic/files/drivers/net/phy/mvsw61xx.c b/target/linux/generic/files/drivers/net/phy/mvsw61xx.c
index 116f6cf..9417fd4 100644
--- a/target/linux/generic/files/drivers/net/phy/mvsw61xx.c
+++ b/target/linux/generic/files/drivers/net/phy/mvsw61xx.c
@@ -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;
diff --git a/target/linux/generic/files/drivers/net/phy/mvsw61xx.h b/target/linux/generic/files/drivers/net/phy/mvsw61xx.h
index 61e134c..dbc6c92 100644
--- a/target/linux/generic/files/drivers/net/phy/mvsw61xx.h
+++ b/target/linux/generic/files/drivers/net/phy/mvsw61xx.h
@@ -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;
-- 
2.1.4
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list