-
Notifications
You must be signed in to change notification settings - Fork 325
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
linux: net: dsa: mt7530: add support for bridge port isolation
Adds bridge port isolation to MT7621-based devices like the Ubiquiti EdgeRouter-X.
- Loading branch information
Showing
1 changed file
with
325 additions
and
0 deletions.
There are no files selected for viewing
325 changes: 325 additions & 0 deletions
325
patches/openwrt/0010-linux-net-dsa-mt7530-add-support-for-bridge-port-isolation.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,325 @@ | ||
From: Matthias Schiffer <[email protected]> | ||
Date: Sat, 15 Jun 2024 01:09:41 +0200 | ||
Subject: linux: net: dsa: mt7530: add support for bridge port isolation | ||
|
||
Backport of from net-next (and one older patch) to Linux 5.15. | ||
|
||
Signed-off-by: Matthias Schiffer <[email protected]> | ||
|
||
diff --git a/target/linux/generic/backport-5.15/850-01-v5.19-net-bridge-offload-BR_HAIRPIN_MODE-BR_ISOLATED-BR_MU.patch b/target/linux/generic/backport-5.15/850-01-v5.19-net-bridge-offload-BR_HAIRPIN_MODE-BR_ISOLATED-BR_MU.patch | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..92234bde024882ecd81c1116279408963f33354e | ||
--- /dev/null | ||
+++ b/target/linux/generic/backport-5.15/850-01-v5.19-net-bridge-offload-BR_HAIRPIN_MODE-BR_ISOLATED-BR_MU.patch | ||
@@ -0,0 +1,44 @@ | ||
+From c3976a3f84451ca05ea5be013af6071bf9acab2c Mon Sep 17 00:00:00 2001 | ||
+Message-ID: <c3976a3f84451ca05ea5be013af6071bf9acab2c.1718445041.git.mschiffer@universe-factory.net> | ||
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <[email protected]> | ||
+Date: Sun, 10 Apr 2022 16:42:27 +0300 | ||
+Subject: [PATCH] net: bridge: offload BR_HAIRPIN_MODE, BR_ISOLATED, | ||
+ BR_MULTICAST_TO_UNICAST | ||
+MIME-Version: 1.0 | ||
+Content-Type: text/plain; charset=UTF-8 | ||
+Content-Transfer-Encoding: 8bit | ||
+ | ||
+Add BR_HAIRPIN_MODE, BR_ISOLATED and BR_MULTICAST_TO_UNICAST port flags to | ||
+BR_PORT_FLAGS_HW_OFFLOAD so that switchdev drivers which have an offloaded | ||
+data plane have a chance to reject these bridge port flags if they don't | ||
+support them yet. | ||
+ | ||
+It makes the code path go through the | ||
+SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS driver handlers, which return | ||
+-EINVAL for everything they don't recognize. | ||
+ | ||
+For drivers that don't catch SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS at | ||
+all, switchdev will return -EOPNOTSUPP for those which is then ignored, but | ||
+those are in the minority. | ||
+ | ||
+Signed-off-by: Arınç ÜNAL <[email protected]> | ||
+Reviewed-by: Ido Schimmel <[email protected]> | ||
+Reviewed-by: Vladimir Oltean <[email protected]> | ||
+Link: https://lore.kernel.org/r/[email protected] | ||
+Signed-off-by: Jakub Kicinski <[email protected]> | ||
+--- | ||
+ net/bridge/br_switchdev.c | 3 ++- | ||
+ 1 file changed, 2 insertions(+), 1 deletion(-) | ||
+ | ||
+--- a/net/bridge/br_switchdev.c | ||
++++ b/net/bridge/br_switchdev.c | ||
+@@ -71,7 +71,8 @@ bool nbp_switchdev_allowed_egress(const | ||
+ | ||
+ /* Flags that can be offloaded to hardware */ | ||
+ #define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \ | ||
+- BR_MCAST_FLOOD | BR_BCAST_FLOOD) | ||
++ BR_MCAST_FLOOD | BR_BCAST_FLOOD | \ | ||
++ BR_HAIRPIN_MODE | BR_ISOLATED | BR_MULTICAST_TO_UNICAST) | ||
+ | ||
+ int br_switchdev_set_port_flag(struct net_bridge_port *p, | ||
+ unsigned long flags, | ||
diff --git a/target/linux/generic/backport-5.15/850-02-v6.11-net-dsa-mt7530-factor-out-bridge-join-leave-logic.patch b/target/linux/generic/backport-5.15/850-02-v6.11-net-dsa-mt7530-factor-out-bridge-join-leave-logic.patch | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..41dc502395d1985b008806af6a6eee42fb2de2d1 | ||
--- /dev/null | ||
+++ b/target/linux/generic/backport-5.15/850-02-v6.11-net-dsa-mt7530-factor-out-bridge-join-leave-logic.patch | ||
@@ -0,0 +1,176 @@ | ||
+From c25c961fc7f36682f0a530150f1b7453ebc344cd Mon Sep 17 00:00:00 2001 | ||
+From: Matthias Schiffer <[email protected]> | ||
+Date: Tue, 18 Jun 2024 09:17:12 +0200 | ||
+Subject: [PATCH 1/2] net: dsa: mt7530: factor out bridge join/leave logic | ||
+MIME-Version: 1.0 | ||
+Content-Type: text/plain; charset=UTF-8 | ||
+Content-Transfer-Encoding: 8bit | ||
+ | ||
+As preparation for implementing bridge port isolation, move the logic to | ||
+add and remove bits in the port matrix into a new helper | ||
+mt7530_update_port_member(), which is called from | ||
+mt7530_port_bridge_join() and mt7530_port_bridge_leave(). | ||
+ | ||
+Another part of the preparation is using dsa_port_offloads_bridge_dev() | ||
+instead of dsa_port_offloads_bridge() to check for bridge membership, as | ||
+we don't have a struct dsa_bridge in mt7530_port_bridge_flags(). | ||
+ | ||
+The port matrix setting is slightly streamlined, now always first setting | ||
+the mt7530_port's pm field and then writing the port matrix from that | ||
+field into the hardware register, instead of duplicating the bit | ||
+manipulation for both the struct field and the register. | ||
+ | ||
+mt7530_port_bridge_join() was previously using |= to update the port | ||
+matrix with the port bitmap, which was unnecessary, as pm would only | ||
+have the CPU port set before joining a bridge; a simple assignment can | ||
+be used for both joining and leaving (and will also work when individual | ||
+bits are added/removed in port_bitmap with regard to the previous port | ||
+matrix, which is what happens with port isolation). | ||
+ | ||
+No functional change intended. | ||
+ | ||
+Signed-off-by: Matthias Schiffer <[email protected]> | ||
+Reviewed-by: Wojciech Drewek <[email protected]> | ||
+Reviewed-by: Arınç ÜNAL <[email protected]> | ||
+Tested-by: Arınç ÜNAL <[email protected]> | ||
+Signed-off-by: David S. Miller <[email protected]> | ||
+--- | ||
+ drivers/net/dsa/mt7530.c | 105 ++++++++++++++++++--------------------- | ||
+ 1 file changed, 48 insertions(+), 57 deletions(-) | ||
+ | ||
+--- a/drivers/net/dsa/mt7530.c | ||
++++ b/drivers/net/dsa/mt7530.c | ||
+@@ -1386,6 +1386,52 @@ mt7530_stp_state_set(struct dsa_switch * | ||
+ FID_PST(FID_BRIDGED, stp_state)); | ||
+ } | ||
+ | ||
++static void mt7530_update_port_member(struct mt7530_priv *priv, int port, | ||
++ const struct net_device *bridge_dev, | ||
++ bool join) __must_hold(&priv->reg_mutex) | ||
++{ | ||
++ struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp; | ||
++ struct mt7530_port *p = &priv->ports[port], *other_p; | ||
++ struct dsa_port *cpu_dp = dp->cpu_dp; | ||
++ u32 port_bitmap = BIT(cpu_dp->index); | ||
++ int other_port; | ||
++ | ||
++ dsa_switch_for_each_user_port(other_dp, priv->ds) { | ||
++ other_port = other_dp->index; | ||
++ other_p = &priv->ports[other_port]; | ||
++ | ||
++ if (dp == other_dp) | ||
++ continue; | ||
++ | ||
++ /* Add/remove this port to/from the port matrix of the other | ||
++ * ports in the same bridge. If the port is disabled, port | ||
++ * matrix is kept and not being setup until the port becomes | ||
++ * enabled. | ||
++ */ | ||
++ if (other_dp->bridge_dev != bridge_dev) | ||
++ continue; | ||
++ | ||
++ if (join) { | ||
++ other_p->pm |= PCR_MATRIX(BIT(port)); | ||
++ port_bitmap |= BIT(other_port); | ||
++ } else { | ||
++ other_p->pm &= ~PCR_MATRIX(BIT(port)); | ||
++ } | ||
++ | ||
++ if (other_p->enable) | ||
++ mt7530_rmw(priv, MT7530_PCR_P(other_port), | ||
++ PCR_MATRIX_MASK, other_p->pm); | ||
++ } | ||
++ | ||
++ /* Add/remove the all other ports to this port matrix. For !join | ||
++ * (leaving the bridge), only the CPU port will remain in the port matrix | ||
++ * of this port. | ||
++ */ | ||
++ p->pm = PCR_MATRIX(port_bitmap); | ||
++ if (priv->ports[port].enable) | ||
++ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, p->pm); | ||
++} | ||
++ | ||
+ static int | ||
+ mt7530_port_pre_bridge_flags(struct dsa_switch *ds, int port, | ||
+ struct switchdev_brport_flags flags, | ||
+@@ -1428,39 +1474,11 @@ static int | ||
+ mt7530_port_bridge_join(struct dsa_switch *ds, int port, | ||
+ struct net_device *bridge) | ||
+ { | ||
+- struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; | ||
+- struct dsa_port *cpu_dp = dp->cpu_dp; | ||
+- u32 port_bitmap = BIT(cpu_dp->index); | ||
+ struct mt7530_priv *priv = ds->priv; | ||
+ | ||
+ mutex_lock(&priv->reg_mutex); | ||
+ | ||
+- dsa_switch_for_each_user_port(other_dp, ds) { | ||
+- int other_port = other_dp->index; | ||
+- | ||
+- if (dp == other_dp) | ||
+- continue; | ||
+- | ||
+- /* Add this port to the port matrix of the other ports in the | ||
+- * same bridge. If the port is disabled, port matrix is kept | ||
+- * and not being setup until the port becomes enabled. | ||
+- */ | ||
+- if (other_dp->bridge_dev != bridge) | ||
+- continue; | ||
+- | ||
+- if (priv->ports[other_port].enable) | ||
+- mt7530_set(priv, MT7530_PCR_P(other_port), | ||
+- PCR_MATRIX(BIT(port))); | ||
+- priv->ports[other_port].pm |= PCR_MATRIX(BIT(port)); | ||
+- | ||
+- port_bitmap |= BIT(other_port); | ||
+- } | ||
+- | ||
+- /* Add the all other ports to this port matrix. */ | ||
+- if (priv->ports[port].enable) | ||
+- mt7530_rmw(priv, MT7530_PCR_P(port), | ||
+- PCR_MATRIX_MASK, PCR_MATRIX(port_bitmap)); | ||
+- priv->ports[port].pm |= PCR_MATRIX(port_bitmap); | ||
++ mt7530_update_port_member(priv, port, bridge, true); | ||
+ | ||
+ /* Set to fallback mode for independent VLAN learning */ | ||
+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, | ||
+@@ -1561,38 +1579,11 @@ static void | ||
+ mt7530_port_bridge_leave(struct dsa_switch *ds, int port, | ||
+ struct net_device *bridge) | ||
+ { | ||
+- struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; | ||
+- struct dsa_port *cpu_dp = dp->cpu_dp; | ||
+ struct mt7530_priv *priv = ds->priv; | ||
+ | ||
+ mutex_lock(&priv->reg_mutex); | ||
+ | ||
+- dsa_switch_for_each_user_port(other_dp, ds) { | ||
+- int other_port = other_dp->index; | ||
+- | ||
+- if (dp == other_dp) | ||
+- continue; | ||
+- | ||
+- /* Remove this port from the port matrix of the other ports | ||
+- * in the same bridge. If the port is disabled, port matrix | ||
+- * is kept and not being setup until the port becomes enabled. | ||
+- */ | ||
+- if (other_dp->bridge_dev != bridge) | ||
+- continue; | ||
+- | ||
+- if (priv->ports[other_port].enable) | ||
+- mt7530_clear(priv, MT7530_PCR_P(other_port), | ||
+- PCR_MATRIX(BIT(port))); | ||
+- priv->ports[other_port].pm &= ~PCR_MATRIX(BIT(port)); | ||
+- } | ||
+- | ||
+- /* Set the cpu port to be the only one in the port matrix of | ||
+- * this port. | ||
+- */ | ||
+- if (priv->ports[port].enable) | ||
+- mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, | ||
+- PCR_MATRIX(BIT(cpu_dp->index))); | ||
+- priv->ports[port].pm = PCR_MATRIX(BIT(cpu_dp->index)); | ||
++ mt7530_update_port_member(priv, port, bridge, false); | ||
+ | ||
+ /* When a port is removed from the bridge, the port would be set up | ||
+ * back to the default as is at initial boot which is a VLAN-unaware | ||
diff --git a/target/linux/generic/backport-5.15/850-03-v6.11-net-dsa-mt7530-add-support-for-bridge-port-isolation.patch b/target/linux/generic/backport-5.15/850-03-v6.11-net-dsa-mt7530-add-support-for-bridge-port-isolation.patch | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..c96531c9abdea94b0ffeeaf8e12e3a62ae6108e5 | ||
--- /dev/null | ||
+++ b/target/linux/generic/backport-5.15/850-03-v6.11-net-dsa-mt7530-add-support-for-bridge-port-isolation.patch | ||
@@ -0,0 +1,79 @@ | ||
+From 3d49ee2127c26fd2c77944fd2e3168c057f99439 Mon Sep 17 00:00:00 2001 | ||
+From: Matthias Schiffer <[email protected]> | ||
+Date: Tue, 18 Jun 2024 09:17:13 +0200 | ||
+Subject: [PATCH 2/2] net: dsa: mt7530: add support for bridge port isolation | ||
+MIME-Version: 1.0 | ||
+Content-Type: text/plain; charset=UTF-8 | ||
+Content-Transfer-Encoding: 8bit | ||
+ | ||
+Remove a pair of ports from the port matrix when both ports have the | ||
+isolated flag set. | ||
+ | ||
+Signed-off-by: Matthias Schiffer <[email protected]> | ||
+Reviewed-by: Wojciech Drewek <[email protected]> | ||
+Reviewed-by: Arınç ÜNAL <[email protected]> | ||
+Tested-by: Arınç ÜNAL <[email protected]> | ||
+Signed-off-by: David S. Miller <[email protected]> | ||
+--- | ||
+ drivers/net/dsa/mt7530.c | 18 ++++++++++++++++-- | ||
+ drivers/net/dsa/mt7530.h | 1 + | ||
+ 2 files changed, 17 insertions(+), 2 deletions(-) | ||
+ | ||
+--- a/drivers/net/dsa/mt7530.c | ||
++++ b/drivers/net/dsa/mt7530.c | ||
+@@ -1395,6 +1395,7 @@ static void mt7530_update_port_member(st | ||
+ struct dsa_port *cpu_dp = dp->cpu_dp; | ||
+ u32 port_bitmap = BIT(cpu_dp->index); | ||
+ int other_port; | ||
++ bool isolated; | ||
+ | ||
+ dsa_switch_for_each_user_port(other_dp, priv->ds) { | ||
+ other_port = other_dp->index; | ||
+@@ -1411,7 +1412,9 @@ static void mt7530_update_port_member(st | ||
+ if (other_dp->bridge_dev != bridge_dev) | ||
+ continue; | ||
+ | ||
+- if (join) { | ||
++ isolated = p->isolated && other_p->isolated; | ||
++ | ||
++ if (join && !isolated) { | ||
+ other_p->pm |= PCR_MATRIX(BIT(port)); | ||
+ port_bitmap |= BIT(other_port); | ||
+ } else { | ||
+@@ -1438,7 +1441,7 @@ mt7530_port_pre_bridge_flags(struct dsa_ | ||
+ struct netlink_ext_ack *extack) | ||
+ { | ||
+ if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | | ||
+- BR_BCAST_FLOOD)) | ||
++ BR_BCAST_FLOOD | BR_ISOLATED)) | ||
+ return -EINVAL; | ||
+ | ||
+ return 0; | ||
+@@ -1467,6 +1470,17 @@ mt7530_port_bridge_flags(struct dsa_swit | ||
+ mt7530_rmw(priv, MT7530_MFC, BC_FFP(BIT(port)), | ||
+ flags.val & BR_BCAST_FLOOD ? BC_FFP(BIT(port)) : 0); | ||
+ | ||
++ if (flags.mask & BR_ISOLATED) { | ||
++ struct dsa_port *dp = dsa_to_port(ds, port); | ||
++ struct net_device *bridge_dev = dp->bridge_dev; | ||
++ | ||
++ priv->ports[port].isolated = !!(flags.val & BR_ISOLATED); | ||
++ | ||
++ mutex_lock(&priv->reg_mutex); | ||
++ mt7530_update_port_member(priv, port, bridge_dev, true); | ||
++ mutex_unlock(&priv->reg_mutex); | ||
++ } | ||
++ | ||
+ return 0; | ||
+ } | ||
+ | ||
+--- a/drivers/net/dsa/mt7530.h | ||
++++ b/drivers/net/dsa/mt7530.h | ||
+@@ -706,6 +706,7 @@ struct mt7530_fdb { | ||
+ */ | ||
+ struct mt7530_port { | ||
+ bool enable; | ||
++ bool isolated; | ||
+ u32 pm; | ||
+ u16 pvid; | ||
+ struct phylink_pcs *sgmii_pcs; |