-
Notifications
You must be signed in to change notification settings - Fork 324
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
274 additions
and
0 deletions.
There are no files selected for viewing
274 changes: 274 additions & 0 deletions
274
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,274 @@ | ||
From: Matthias Schiffer <mschiffer@universe-factory.net> | ||
Date: Sat, 15 Jun 2024 01:09:41 +0200 | ||
Subject: linux: net: dsa: mt7530: add support for bridge port isolation | ||
|
||
Backport of | ||
https://patchwork.kernel.org/project/netdevbpf/list/?series=862224 (and | ||
one older patch) to Linux 5.15. | ||
|
||
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net> | ||
|
||
diff --git a/target/linux/generic/backport-5.15/850-v5.19-net-bridge-offload-BR_HAIRPIN_MODE-BR_ISOLATED-BR_MU.patch b/target/linux/generic/backport-5.15/850-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-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?= <arinc.unal@arinc9.com> | ||
+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 <arinc.unal@arinc9.com> | ||
+Reviewed-by: Ido Schimmel <idosch@nvidia.com> | ||
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com> | ||
+Link: https://lore.kernel.org/r/20220410134227.18810-1-arinc.unal@arinc9.com | ||
+Signed-off-by: Jakub Kicinski <kuba@kernel.org> | ||
+--- | ||
+ 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/pending-5.15/797-net-dsa-mt7530-factor-out-bridge-join-leave-logic.patch b/target/linux/generic/pending-5.15/797-net-dsa-mt7530-factor-out-bridge-join-leave-logic.patch | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..4c39c9f8589c26ce21e1e30bbdb862bb6b5e2647 | ||
--- /dev/null | ||
+++ b/target/linux/generic/pending-5.15/797-net-dsa-mt7530-factor-out-bridge-join-leave-logic.patch | ||
@@ -0,0 +1,134 @@ | ||
+--- a/drivers/net/dsa/mt7530.c | ||
++++ b/drivers/net/dsa/mt7530.c | ||
+@@ -1386,6 +1386,50 @@ 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. */ | ||
++ 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 +1472,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 +1577,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/pending-5.15/798-net-dsa-mt7530-add-support-for-bridge-port-isolation.patch b/target/linux/generic/pending-5.15/798-net-dsa-mt7530-add-support-for-bridge-port-isolation.patch | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..e9ef751957d93c312a313dfba0502856ddf4eb9e | ||
--- /dev/null | ||
+++ b/target/linux/generic/pending-5.15/798-net-dsa-mt7530-add-support-for-bridge-port-isolation.patch | ||
@@ -0,0 +1,68 @@ | ||
+--- a/drivers/net/dsa/mt7530.c | ||
++++ b/drivers/net/dsa/mt7530.c | ||
+@@ -1387,7 +1387,8 @@ mt7530_stp_state_set(struct dsa_switch * | ||
+ } | ||
+ | ||
+ static void mt7530_update_port_member(struct mt7530_priv *priv, int port, | ||
+- const struct net_device *bridge_dev, bool join) | ||
++ 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; | ||
+@@ -1395,6 +1396,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 +1413,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 { | ||
+@@ -1436,7 +1440,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; | ||
+@@ -1465,6 +1469,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; |