|
| 1 | +From: Matthias Schiffer < [email protected]> |
| 2 | +Date: Sat, 15 Jun 2024 01:09:41 +0200 |
| 3 | +Subject: linux: net: dsa: mt7530: add support for bridge port isolation |
| 4 | + |
| 5 | +Backport of |
| 6 | +https://patchwork.kernel.org/project/netdevbpf/list/?series=862224 (and |
| 7 | +one older patch) to Linux 5.15. |
| 8 | + |
| 9 | +Signed-off-by: Matthias Schiffer < [email protected]> |
| 10 | + |
| 11 | +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 |
| 12 | +new file mode 100644 |
| 13 | +index 0000000000000000000000000000000000000000..92234bde024882ecd81c1116279408963f33354e |
| 14 | +--- /dev/null |
| 15 | ++++ b/target/linux/generic/backport-5.15/850-v5.19-net-bridge-offload-BR_HAIRPIN_MODE-BR_ISOLATED-BR_MU.patch |
| 16 | +@@ -0,0 +1,44 @@ |
| 17 | ++From c3976a3f84451ca05ea5be013af6071bf9acab2c Mon Sep 17 00:00:00 2001 |
| 18 | ++Message-ID: <c3976a3f84451ca05ea5be013af6071bf9acab2c.1718445041.git.mschiffer@universe-factory.net> |
| 19 | ++From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <[email protected]> |
| 20 | ++Date: Sun, 10 Apr 2022 16:42:27 +0300 |
| 21 | ++Subject: [PATCH] net: bridge: offload BR_HAIRPIN_MODE, BR_ISOLATED, |
| 22 | ++ BR_MULTICAST_TO_UNICAST |
| 23 | ++MIME-Version: 1.0 |
| 24 | ++Content-Type: text/plain; charset=UTF-8 |
| 25 | ++Content-Transfer-Encoding: 8bit |
| 26 | ++ |
| 27 | ++Add BR_HAIRPIN_MODE, BR_ISOLATED and BR_MULTICAST_TO_UNICAST port flags to |
| 28 | ++BR_PORT_FLAGS_HW_OFFLOAD so that switchdev drivers which have an offloaded |
| 29 | ++data plane have a chance to reject these bridge port flags if they don't |
| 30 | ++support them yet. |
| 31 | ++ |
| 32 | ++It makes the code path go through the |
| 33 | ++SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS driver handlers, which return |
| 34 | ++-EINVAL for everything they don't recognize. |
| 35 | ++ |
| 36 | ++For drivers that don't catch SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS at |
| 37 | ++all, switchdev will return -EOPNOTSUPP for those which is then ignored, but |
| 38 | ++those are in the minority. |
| 39 | ++ |
| 40 | ++Signed-off-by: Arınç ÜNAL <[email protected]> |
| 41 | ++Reviewed-by: Ido Schimmel <[email protected]> |
| 42 | ++Reviewed-by: Vladimir Oltean <[email protected]> |
| 43 | ++Link: https://lore.kernel.org/r/[email protected] |
| 44 | ++Signed-off-by: Jakub Kicinski <[email protected]> |
| 45 | ++--- |
| 46 | ++ net/bridge/br_switchdev.c | 3 ++- |
| 47 | ++ 1 file changed, 2 insertions(+), 1 deletion(-) |
| 48 | ++ |
| 49 | ++--- a/net/bridge/br_switchdev.c |
| 50 | +++++ b/net/bridge/br_switchdev.c |
| 51 | ++@@ -71,7 +71,8 @@ bool nbp_switchdev_allowed_egress(const |
| 52 | ++ |
| 53 | ++ /* Flags that can be offloaded to hardware */ |
| 54 | ++ #define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \ |
| 55 | ++- BR_MCAST_FLOOD | BR_BCAST_FLOOD) |
| 56 | +++ BR_MCAST_FLOOD | BR_BCAST_FLOOD | \ |
| 57 | +++ BR_HAIRPIN_MODE | BR_ISOLATED | BR_MULTICAST_TO_UNICAST) |
| 58 | ++ |
| 59 | ++ int br_switchdev_set_port_flag(struct net_bridge_port *p, |
| 60 | ++ unsigned long flags, |
| 61 | +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 |
| 62 | +new file mode 100644 |
| 63 | +index 0000000000000000000000000000000000000000..4c39c9f8589c26ce21e1e30bbdb862bb6b5e2647 |
| 64 | +--- /dev/null |
| 65 | ++++ b/target/linux/generic/pending-5.15/797-net-dsa-mt7530-factor-out-bridge-join-leave-logic.patch |
| 66 | +@@ -0,0 +1,134 @@ |
| 67 | ++--- a/drivers/net/dsa/mt7530.c |
| 68 | +++++ b/drivers/net/dsa/mt7530.c |
| 69 | ++@@ -1386,6 +1386,50 @@ mt7530_stp_state_set(struct dsa_switch * |
| 70 | ++ FID_PST(FID_BRIDGED, stp_state)); |
| 71 | ++ } |
| 72 | ++ |
| 73 | +++static void mt7530_update_port_member(struct mt7530_priv *priv, int port, |
| 74 | +++ const struct net_device *bridge_dev, bool join) |
| 75 | +++ __must_hold(&priv->reg_mutex) |
| 76 | +++{ |
| 77 | +++ struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp; |
| 78 | +++ struct mt7530_port *p = &priv->ports[port], *other_p; |
| 79 | +++ struct dsa_port *cpu_dp = dp->cpu_dp; |
| 80 | +++ u32 port_bitmap = BIT(cpu_dp->index); |
| 81 | +++ int other_port; |
| 82 | +++ |
| 83 | +++ dsa_switch_for_each_user_port(other_dp, priv->ds) { |
| 84 | +++ other_port = other_dp->index; |
| 85 | +++ other_p = &priv->ports[other_port]; |
| 86 | +++ |
| 87 | +++ if (dp == other_dp) |
| 88 | +++ continue; |
| 89 | +++ |
| 90 | +++ /* Add/remove this port to/from the port matrix of the other |
| 91 | +++ * ports in the same bridge. If the port is disabled, port |
| 92 | +++ * matrix is kept and not being setup until the port becomes |
| 93 | +++ * enabled. |
| 94 | +++ */ |
| 95 | +++ if (other_dp->bridge_dev != bridge_dev) |
| 96 | +++ continue; |
| 97 | +++ |
| 98 | +++ if (join) { |
| 99 | +++ other_p->pm |= PCR_MATRIX(BIT(port)); |
| 100 | +++ port_bitmap |= BIT(other_port); |
| 101 | +++ } else { |
| 102 | +++ other_p->pm &= ~PCR_MATRIX(BIT(port)); |
| 103 | +++ } |
| 104 | +++ |
| 105 | +++ if (other_p->enable) |
| 106 | +++ mt7530_rmw(priv, MT7530_PCR_P(other_port), |
| 107 | +++ PCR_MATRIX_MASK, other_p->pm); |
| 108 | +++ } |
| 109 | +++ |
| 110 | +++ /* Add/remove the all other ports to this port matrix. */ |
| 111 | +++ p->pm = PCR_MATRIX(port_bitmap); |
| 112 | +++ if (priv->ports[port].enable) |
| 113 | +++ mt7530_rmw(priv, MT7530_PCR_P(port), |
| 114 | +++ PCR_MATRIX_MASK, p->pm); |
| 115 | +++} |
| 116 | +++ |
| 117 | ++ static int |
| 118 | ++ mt7530_port_pre_bridge_flags(struct dsa_switch *ds, int port, |
| 119 | ++ struct switchdev_brport_flags flags, |
| 120 | ++@@ -1428,39 +1472,11 @@ static int |
| 121 | ++ mt7530_port_bridge_join(struct dsa_switch *ds, int port, |
| 122 | ++ struct net_device *bridge) |
| 123 | ++ { |
| 124 | ++- struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; |
| 125 | ++- struct dsa_port *cpu_dp = dp->cpu_dp; |
| 126 | ++- u32 port_bitmap = BIT(cpu_dp->index); |
| 127 | ++ struct mt7530_priv *priv = ds->priv; |
| 128 | ++ |
| 129 | ++ mutex_lock(&priv->reg_mutex); |
| 130 | ++ |
| 131 | ++- dsa_switch_for_each_user_port(other_dp, ds) { |
| 132 | ++- int other_port = other_dp->index; |
| 133 | ++- |
| 134 | ++- if (dp == other_dp) |
| 135 | ++- continue; |
| 136 | ++- |
| 137 | ++- /* Add this port to the port matrix of the other ports in the |
| 138 | ++- * same bridge. If the port is disabled, port matrix is kept |
| 139 | ++- * and not being setup until the port becomes enabled. |
| 140 | ++- */ |
| 141 | ++- if (other_dp->bridge_dev != bridge) |
| 142 | ++- continue; |
| 143 | ++- |
| 144 | ++- if (priv->ports[other_port].enable) |
| 145 | ++- mt7530_set(priv, MT7530_PCR_P(other_port), |
| 146 | ++- PCR_MATRIX(BIT(port))); |
| 147 | ++- priv->ports[other_port].pm |= PCR_MATRIX(BIT(port)); |
| 148 | ++- |
| 149 | ++- port_bitmap |= BIT(other_port); |
| 150 | ++- } |
| 151 | ++- |
| 152 | ++- /* Add the all other ports to this port matrix. */ |
| 153 | ++- if (priv->ports[port].enable) |
| 154 | ++- mt7530_rmw(priv, MT7530_PCR_P(port), |
| 155 | ++- PCR_MATRIX_MASK, PCR_MATRIX(port_bitmap)); |
| 156 | ++- priv->ports[port].pm |= PCR_MATRIX(port_bitmap); |
| 157 | +++ mt7530_update_port_member(priv, port, bridge, true); |
| 158 | ++ |
| 159 | ++ /* Set to fallback mode for independent VLAN learning */ |
| 160 | ++ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, |
| 161 | ++@@ -1561,38 +1577,11 @@ static void |
| 162 | ++ mt7530_port_bridge_leave(struct dsa_switch *ds, int port, |
| 163 | ++ struct net_device *bridge) |
| 164 | ++ { |
| 165 | ++- struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; |
| 166 | ++- struct dsa_port *cpu_dp = dp->cpu_dp; |
| 167 | ++ struct mt7530_priv *priv = ds->priv; |
| 168 | ++ |
| 169 | ++ mutex_lock(&priv->reg_mutex); |
| 170 | ++ |
| 171 | ++- dsa_switch_for_each_user_port(other_dp, ds) { |
| 172 | ++- int other_port = other_dp->index; |
| 173 | ++- |
| 174 | ++- if (dp == other_dp) |
| 175 | ++- continue; |
| 176 | ++- |
| 177 | ++- /* Remove this port from the port matrix of the other ports |
| 178 | ++- * in the same bridge. If the port is disabled, port matrix |
| 179 | ++- * is kept and not being setup until the port becomes enabled. |
| 180 | ++- */ |
| 181 | ++- if (other_dp->bridge_dev != bridge) |
| 182 | ++- continue; |
| 183 | ++- |
| 184 | ++- if (priv->ports[other_port].enable) |
| 185 | ++- mt7530_clear(priv, MT7530_PCR_P(other_port), |
| 186 | ++- PCR_MATRIX(BIT(port))); |
| 187 | ++- priv->ports[other_port].pm &= ~PCR_MATRIX(BIT(port)); |
| 188 | ++- } |
| 189 | ++- |
| 190 | ++- /* Set the cpu port to be the only one in the port matrix of |
| 191 | ++- * this port. |
| 192 | ++- */ |
| 193 | ++- if (priv->ports[port].enable) |
| 194 | ++- mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, |
| 195 | ++- PCR_MATRIX(BIT(cpu_dp->index))); |
| 196 | ++- priv->ports[port].pm = PCR_MATRIX(BIT(cpu_dp->index)); |
| 197 | +++ mt7530_update_port_member(priv, port, bridge, false); |
| 198 | ++ |
| 199 | ++ /* When a port is removed from the bridge, the port would be set up |
| 200 | ++ * back to the default as is at initial boot which is a VLAN-unaware |
| 201 | +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 |
| 202 | +new file mode 100644 |
| 203 | +index 0000000000000000000000000000000000000000..e9ef751957d93c312a313dfba0502856ddf4eb9e |
| 204 | +--- /dev/null |
| 205 | ++++ b/target/linux/generic/pending-5.15/798-net-dsa-mt7530-add-support-for-bridge-port-isolation.patch |
| 206 | +@@ -0,0 +1,68 @@ |
| 207 | ++--- a/drivers/net/dsa/mt7530.c |
| 208 | +++++ b/drivers/net/dsa/mt7530.c |
| 209 | ++@@ -1387,7 +1387,8 @@ mt7530_stp_state_set(struct dsa_switch * |
| 210 | ++ } |
| 211 | ++ |
| 212 | ++ static void mt7530_update_port_member(struct mt7530_priv *priv, int port, |
| 213 | ++- const struct net_device *bridge_dev, bool join) |
| 214 | +++ const struct net_device *bridge_dev, |
| 215 | +++ bool join) |
| 216 | ++ __must_hold(&priv->reg_mutex) |
| 217 | ++ { |
| 218 | ++ struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp; |
| 219 | ++@@ -1395,6 +1396,7 @@ static void mt7530_update_port_member(st |
| 220 | ++ struct dsa_port *cpu_dp = dp->cpu_dp; |
| 221 | ++ u32 port_bitmap = BIT(cpu_dp->index); |
| 222 | ++ int other_port; |
| 223 | +++ bool isolated; |
| 224 | ++ |
| 225 | ++ dsa_switch_for_each_user_port(other_dp, priv->ds) { |
| 226 | ++ other_port = other_dp->index; |
| 227 | ++@@ -1411,7 +1413,9 @@ static void mt7530_update_port_member(st |
| 228 | ++ if (other_dp->bridge_dev != bridge_dev) |
| 229 | ++ continue; |
| 230 | ++ |
| 231 | ++- if (join) { |
| 232 | +++ isolated = p->isolated && other_p->isolated; |
| 233 | +++ |
| 234 | +++ if (join && !isolated) { |
| 235 | ++ other_p->pm |= PCR_MATRIX(BIT(port)); |
| 236 | ++ port_bitmap |= BIT(other_port); |
| 237 | ++ } else { |
| 238 | ++@@ -1436,7 +1440,7 @@ mt7530_port_pre_bridge_flags(struct dsa_ |
| 239 | ++ struct netlink_ext_ack *extack) |
| 240 | ++ { |
| 241 | ++ if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | |
| 242 | ++- BR_BCAST_FLOOD)) |
| 243 | +++ BR_BCAST_FLOOD | BR_ISOLATED)) |
| 244 | ++ return -EINVAL; |
| 245 | ++ |
| 246 | ++ return 0; |
| 247 | ++@@ -1465,6 +1469,17 @@ mt7530_port_bridge_flags(struct dsa_swit |
| 248 | ++ mt7530_rmw(priv, MT7530_MFC, BC_FFP(BIT(port)), |
| 249 | ++ flags.val & BR_BCAST_FLOOD ? BC_FFP(BIT(port)) : 0); |
| 250 | ++ |
| 251 | +++ if (flags.mask & BR_ISOLATED) { |
| 252 | +++ struct dsa_port *dp = dsa_to_port(ds, port); |
| 253 | +++ struct net_device *bridge_dev = dp->bridge_dev; |
| 254 | +++ |
| 255 | +++ priv->ports[port].isolated = !!(flags.val & BR_ISOLATED); |
| 256 | +++ |
| 257 | +++ mutex_lock(&priv->reg_mutex); |
| 258 | +++ mt7530_update_port_member(priv, port, bridge_dev, true); |
| 259 | +++ mutex_unlock(&priv->reg_mutex); |
| 260 | +++ } |
| 261 | +++ |
| 262 | ++ return 0; |
| 263 | ++ } |
| 264 | ++ |
| 265 | ++--- a/drivers/net/dsa/mt7530.h |
| 266 | +++++ b/drivers/net/dsa/mt7530.h |
| 267 | ++@@ -706,6 +706,7 @@ struct mt7530_fdb { |
| 268 | ++ */ |
| 269 | ++ struct mt7530_port { |
| 270 | ++ bool enable; |
| 271 | +++ bool isolated; |
| 272 | ++ u32 pm; |
| 273 | ++ u16 pvid; |
| 274 | ++ struct phylink_pcs *sgmii_pcs; |
0 commit comments