|
| 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 from net-next (and one older patch) to Linux 5.15. |
| 6 | + |
| 7 | +Signed-off-by: Matthias Schiffer < [email protected]> |
| 8 | + |
| 9 | +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 |
| 10 | +new file mode 100644 |
| 11 | +index 0000000000000000000000000000000000000000..92234bde024882ecd81c1116279408963f33354e |
| 12 | +--- /dev/null |
| 13 | ++++ b/target/linux/generic/backport-5.15/850-01-v5.19-net-bridge-offload-BR_HAIRPIN_MODE-BR_ISOLATED-BR_MU.patch |
| 14 | +@@ -0,0 +1,44 @@ |
| 15 | ++From c3976a3f84451ca05ea5be013af6071bf9acab2c Mon Sep 17 00:00:00 2001 |
| 16 | ++Message-ID: <c3976a3f84451ca05ea5be013af6071bf9acab2c.1718445041.git.mschiffer@universe-factory.net> |
| 17 | ++From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <[email protected]> |
| 18 | ++Date: Sun, 10 Apr 2022 16:42:27 +0300 |
| 19 | ++Subject: [PATCH] net: bridge: offload BR_HAIRPIN_MODE, BR_ISOLATED, |
| 20 | ++ BR_MULTICAST_TO_UNICAST |
| 21 | ++MIME-Version: 1.0 |
| 22 | ++Content-Type: text/plain; charset=UTF-8 |
| 23 | ++Content-Transfer-Encoding: 8bit |
| 24 | ++ |
| 25 | ++Add BR_HAIRPIN_MODE, BR_ISOLATED and BR_MULTICAST_TO_UNICAST port flags to |
| 26 | ++BR_PORT_FLAGS_HW_OFFLOAD so that switchdev drivers which have an offloaded |
| 27 | ++data plane have a chance to reject these bridge port flags if they don't |
| 28 | ++support them yet. |
| 29 | ++ |
| 30 | ++It makes the code path go through the |
| 31 | ++SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS driver handlers, which return |
| 32 | ++-EINVAL for everything they don't recognize. |
| 33 | ++ |
| 34 | ++For drivers that don't catch SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS at |
| 35 | ++all, switchdev will return -EOPNOTSUPP for those which is then ignored, but |
| 36 | ++those are in the minority. |
| 37 | ++ |
| 38 | ++Signed-off-by: Arınç ÜNAL <[email protected]> |
| 39 | ++Reviewed-by: Ido Schimmel <[email protected]> |
| 40 | ++Reviewed-by: Vladimir Oltean <[email protected]> |
| 41 | ++Link: https://lore.kernel.org/r/[email protected] |
| 42 | ++Signed-off-by: Jakub Kicinski <[email protected]> |
| 43 | ++--- |
| 44 | ++ net/bridge/br_switchdev.c | 3 ++- |
| 45 | ++ 1 file changed, 2 insertions(+), 1 deletion(-) |
| 46 | ++ |
| 47 | ++--- a/net/bridge/br_switchdev.c |
| 48 | +++++ b/net/bridge/br_switchdev.c |
| 49 | ++@@ -71,7 +71,8 @@ bool nbp_switchdev_allowed_egress(const |
| 50 | ++ |
| 51 | ++ /* Flags that can be offloaded to hardware */ |
| 52 | ++ #define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \ |
| 53 | ++- BR_MCAST_FLOOD | BR_BCAST_FLOOD) |
| 54 | +++ BR_MCAST_FLOOD | BR_BCAST_FLOOD | \ |
| 55 | +++ BR_HAIRPIN_MODE | BR_ISOLATED | BR_MULTICAST_TO_UNICAST) |
| 56 | ++ |
| 57 | ++ int br_switchdev_set_port_flag(struct net_bridge_port *p, |
| 58 | ++ unsigned long flags, |
| 59 | +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 |
| 60 | +new file mode 100644 |
| 61 | +index 0000000000000000000000000000000000000000..41dc502395d1985b008806af6a6eee42fb2de2d1 |
| 62 | +--- /dev/null |
| 63 | ++++ b/target/linux/generic/backport-5.15/850-02-v6.11-net-dsa-mt7530-factor-out-bridge-join-leave-logic.patch |
| 64 | +@@ -0,0 +1,176 @@ |
| 65 | ++From c25c961fc7f36682f0a530150f1b7453ebc344cd Mon Sep 17 00:00:00 2001 |
| 66 | ++From: Matthias Schiffer <[email protected]> |
| 67 | ++Date: Tue, 18 Jun 2024 09:17:12 +0200 |
| 68 | ++Subject: [PATCH 1/2] net: dsa: mt7530: factor out bridge join/leave logic |
| 69 | ++MIME-Version: 1.0 |
| 70 | ++Content-Type: text/plain; charset=UTF-8 |
| 71 | ++Content-Transfer-Encoding: 8bit |
| 72 | ++ |
| 73 | ++As preparation for implementing bridge port isolation, move the logic to |
| 74 | ++add and remove bits in the port matrix into a new helper |
| 75 | ++mt7530_update_port_member(), which is called from |
| 76 | ++mt7530_port_bridge_join() and mt7530_port_bridge_leave(). |
| 77 | ++ |
| 78 | ++Another part of the preparation is using dsa_port_offloads_bridge_dev() |
| 79 | ++instead of dsa_port_offloads_bridge() to check for bridge membership, as |
| 80 | ++we don't have a struct dsa_bridge in mt7530_port_bridge_flags(). |
| 81 | ++ |
| 82 | ++The port matrix setting is slightly streamlined, now always first setting |
| 83 | ++the mt7530_port's pm field and then writing the port matrix from that |
| 84 | ++field into the hardware register, instead of duplicating the bit |
| 85 | ++manipulation for both the struct field and the register. |
| 86 | ++ |
| 87 | ++mt7530_port_bridge_join() was previously using |= to update the port |
| 88 | ++matrix with the port bitmap, which was unnecessary, as pm would only |
| 89 | ++have the CPU port set before joining a bridge; a simple assignment can |
| 90 | ++be used for both joining and leaving (and will also work when individual |
| 91 | ++bits are added/removed in port_bitmap with regard to the previous port |
| 92 | ++matrix, which is what happens with port isolation). |
| 93 | ++ |
| 94 | ++No functional change intended. |
| 95 | ++ |
| 96 | ++Signed-off-by: Matthias Schiffer <[email protected]> |
| 97 | ++Reviewed-by: Wojciech Drewek <[email protected]> |
| 98 | ++Reviewed-by: Arınç ÜNAL <[email protected]> |
| 99 | ++Tested-by: Arınç ÜNAL <[email protected]> |
| 100 | ++Signed-off-by: David S. Miller <[email protected]> |
| 101 | ++--- |
| 102 | ++ drivers/net/dsa/mt7530.c | 105 ++++++++++++++++++--------------------- |
| 103 | ++ 1 file changed, 48 insertions(+), 57 deletions(-) |
| 104 | ++ |
| 105 | ++--- a/drivers/net/dsa/mt7530.c |
| 106 | +++++ b/drivers/net/dsa/mt7530.c |
| 107 | ++@@ -1386,6 +1386,52 @@ mt7530_stp_state_set(struct dsa_switch * |
| 108 | ++ FID_PST(FID_BRIDGED, stp_state)); |
| 109 | ++ } |
| 110 | ++ |
| 111 | +++static void mt7530_update_port_member(struct mt7530_priv *priv, int port, |
| 112 | +++ const struct net_device *bridge_dev, |
| 113 | +++ bool join) __must_hold(&priv->reg_mutex) |
| 114 | +++{ |
| 115 | +++ struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp; |
| 116 | +++ struct mt7530_port *p = &priv->ports[port], *other_p; |
| 117 | +++ struct dsa_port *cpu_dp = dp->cpu_dp; |
| 118 | +++ u32 port_bitmap = BIT(cpu_dp->index); |
| 119 | +++ int other_port; |
| 120 | +++ |
| 121 | +++ dsa_switch_for_each_user_port(other_dp, priv->ds) { |
| 122 | +++ other_port = other_dp->index; |
| 123 | +++ other_p = &priv->ports[other_port]; |
| 124 | +++ |
| 125 | +++ if (dp == other_dp) |
| 126 | +++ continue; |
| 127 | +++ |
| 128 | +++ /* Add/remove this port to/from the port matrix of the other |
| 129 | +++ * ports in the same bridge. If the port is disabled, port |
| 130 | +++ * matrix is kept and not being setup until the port becomes |
| 131 | +++ * enabled. |
| 132 | +++ */ |
| 133 | +++ if (other_dp->bridge_dev != bridge_dev) |
| 134 | +++ continue; |
| 135 | +++ |
| 136 | +++ if (join) { |
| 137 | +++ other_p->pm |= PCR_MATRIX(BIT(port)); |
| 138 | +++ port_bitmap |= BIT(other_port); |
| 139 | +++ } else { |
| 140 | +++ other_p->pm &= ~PCR_MATRIX(BIT(port)); |
| 141 | +++ } |
| 142 | +++ |
| 143 | +++ if (other_p->enable) |
| 144 | +++ mt7530_rmw(priv, MT7530_PCR_P(other_port), |
| 145 | +++ PCR_MATRIX_MASK, other_p->pm); |
| 146 | +++ } |
| 147 | +++ |
| 148 | +++ /* Add/remove the all other ports to this port matrix. For !join |
| 149 | +++ * (leaving the bridge), only the CPU port will remain in the port matrix |
| 150 | +++ * of this port. |
| 151 | +++ */ |
| 152 | +++ p->pm = PCR_MATRIX(port_bitmap); |
| 153 | +++ if (priv->ports[port].enable) |
| 154 | +++ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, p->pm); |
| 155 | +++} |
| 156 | +++ |
| 157 | ++ static int |
| 158 | ++ mt7530_port_pre_bridge_flags(struct dsa_switch *ds, int port, |
| 159 | ++ struct switchdev_brport_flags flags, |
| 160 | ++@@ -1428,39 +1474,11 @@ static int |
| 161 | ++ mt7530_port_bridge_join(struct dsa_switch *ds, int port, |
| 162 | ++ struct net_device *bridge) |
| 163 | ++ { |
| 164 | ++- struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; |
| 165 | ++- struct dsa_port *cpu_dp = dp->cpu_dp; |
| 166 | ++- u32 port_bitmap = BIT(cpu_dp->index); |
| 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 | ++- /* Add this port to the port matrix of the other ports in the |
| 178 | ++- * same bridge. If the port is disabled, port matrix is kept |
| 179 | ++- * 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_set(priv, MT7530_PCR_P(other_port), |
| 186 | ++- PCR_MATRIX(BIT(port))); |
| 187 | ++- priv->ports[other_port].pm |= PCR_MATRIX(BIT(port)); |
| 188 | ++- |
| 189 | ++- port_bitmap |= BIT(other_port); |
| 190 | ++- } |
| 191 | ++- |
| 192 | ++- /* Add the all other ports to this port matrix. */ |
| 193 | ++- if (priv->ports[port].enable) |
| 194 | ++- mt7530_rmw(priv, MT7530_PCR_P(port), |
| 195 | ++- PCR_MATRIX_MASK, PCR_MATRIX(port_bitmap)); |
| 196 | ++- priv->ports[port].pm |= PCR_MATRIX(port_bitmap); |
| 197 | +++ mt7530_update_port_member(priv, port, bridge, true); |
| 198 | ++ |
| 199 | ++ /* Set to fallback mode for independent VLAN learning */ |
| 200 | ++ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK, |
| 201 | ++@@ -1561,38 +1579,11 @@ static void |
| 202 | ++ mt7530_port_bridge_leave(struct dsa_switch *ds, int port, |
| 203 | ++ struct net_device *bridge) |
| 204 | ++ { |
| 205 | ++- struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; |
| 206 | ++- struct dsa_port *cpu_dp = dp->cpu_dp; |
| 207 | ++ struct mt7530_priv *priv = ds->priv; |
| 208 | ++ |
| 209 | ++ mutex_lock(&priv->reg_mutex); |
| 210 | ++ |
| 211 | ++- dsa_switch_for_each_user_port(other_dp, ds) { |
| 212 | ++- int other_port = other_dp->index; |
| 213 | ++- |
| 214 | ++- if (dp == other_dp) |
| 215 | ++- continue; |
| 216 | ++- |
| 217 | ++- /* Remove this port from the port matrix of the other ports |
| 218 | ++- * in the same bridge. If the port is disabled, port matrix |
| 219 | ++- * is kept and not being setup until the port becomes enabled. |
| 220 | ++- */ |
| 221 | ++- if (other_dp->bridge_dev != bridge) |
| 222 | ++- continue; |
| 223 | ++- |
| 224 | ++- if (priv->ports[other_port].enable) |
| 225 | ++- mt7530_clear(priv, MT7530_PCR_P(other_port), |
| 226 | ++- PCR_MATRIX(BIT(port))); |
| 227 | ++- priv->ports[other_port].pm &= ~PCR_MATRIX(BIT(port)); |
| 228 | ++- } |
| 229 | ++- |
| 230 | ++- /* Set the cpu port to be the only one in the port matrix of |
| 231 | ++- * this port. |
| 232 | ++- */ |
| 233 | ++- if (priv->ports[port].enable) |
| 234 | ++- mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, |
| 235 | ++- PCR_MATRIX(BIT(cpu_dp->index))); |
| 236 | ++- priv->ports[port].pm = PCR_MATRIX(BIT(cpu_dp->index)); |
| 237 | +++ mt7530_update_port_member(priv, port, bridge, false); |
| 238 | ++ |
| 239 | ++ /* When a port is removed from the bridge, the port would be set up |
| 240 | ++ * back to the default as is at initial boot which is a VLAN-unaware |
| 241 | +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 |
| 242 | +new file mode 100644 |
| 243 | +index 0000000000000000000000000000000000000000..c96531c9abdea94b0ffeeaf8e12e3a62ae6108e5 |
| 244 | +--- /dev/null |
| 245 | ++++ b/target/linux/generic/backport-5.15/850-03-v6.11-net-dsa-mt7530-add-support-for-bridge-port-isolation.patch |
| 246 | +@@ -0,0 +1,79 @@ |
| 247 | ++From 3d49ee2127c26fd2c77944fd2e3168c057f99439 Mon Sep 17 00:00:00 2001 |
| 248 | ++From: Matthias Schiffer <[email protected]> |
| 249 | ++Date: Tue, 18 Jun 2024 09:17:13 +0200 |
| 250 | ++Subject: [PATCH 2/2] net: dsa: mt7530: add support for bridge port isolation |
| 251 | ++MIME-Version: 1.0 |
| 252 | ++Content-Type: text/plain; charset=UTF-8 |
| 253 | ++Content-Transfer-Encoding: 8bit |
| 254 | ++ |
| 255 | ++Remove a pair of ports from the port matrix when both ports have the |
| 256 | ++isolated flag set. |
| 257 | ++ |
| 258 | ++Signed-off-by: Matthias Schiffer <[email protected]> |
| 259 | ++Reviewed-by: Wojciech Drewek <[email protected]> |
| 260 | ++Reviewed-by: Arınç ÜNAL <[email protected]> |
| 261 | ++Tested-by: Arınç ÜNAL <[email protected]> |
| 262 | ++Signed-off-by: David S. Miller <[email protected]> |
| 263 | ++--- |
| 264 | ++ drivers/net/dsa/mt7530.c | 18 ++++++++++++++++-- |
| 265 | ++ drivers/net/dsa/mt7530.h | 1 + |
| 266 | ++ 2 files changed, 17 insertions(+), 2 deletions(-) |
| 267 | ++ |
| 268 | ++--- a/drivers/net/dsa/mt7530.c |
| 269 | +++++ b/drivers/net/dsa/mt7530.c |
| 270 | ++@@ -1395,6 +1395,7 @@ static void mt7530_update_port_member(st |
| 271 | ++ struct dsa_port *cpu_dp = dp->cpu_dp; |
| 272 | ++ u32 port_bitmap = BIT(cpu_dp->index); |
| 273 | ++ int other_port; |
| 274 | +++ bool isolated; |
| 275 | ++ |
| 276 | ++ dsa_switch_for_each_user_port(other_dp, priv->ds) { |
| 277 | ++ other_port = other_dp->index; |
| 278 | ++@@ -1411,7 +1412,9 @@ static void mt7530_update_port_member(st |
| 279 | ++ if (other_dp->bridge_dev != bridge_dev) |
| 280 | ++ continue; |
| 281 | ++ |
| 282 | ++- if (join) { |
| 283 | +++ isolated = p->isolated && other_p->isolated; |
| 284 | +++ |
| 285 | +++ if (join && !isolated) { |
| 286 | ++ other_p->pm |= PCR_MATRIX(BIT(port)); |
| 287 | ++ port_bitmap |= BIT(other_port); |
| 288 | ++ } else { |
| 289 | ++@@ -1438,7 +1441,7 @@ mt7530_port_pre_bridge_flags(struct dsa_ |
| 290 | ++ struct netlink_ext_ack *extack) |
| 291 | ++ { |
| 292 | ++ if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | |
| 293 | ++- BR_BCAST_FLOOD)) |
| 294 | +++ BR_BCAST_FLOOD | BR_ISOLATED)) |
| 295 | ++ return -EINVAL; |
| 296 | ++ |
| 297 | ++ return 0; |
| 298 | ++@@ -1467,6 +1470,17 @@ mt7530_port_bridge_flags(struct dsa_swit |
| 299 | ++ mt7530_rmw(priv, MT7530_MFC, BC_FFP(BIT(port)), |
| 300 | ++ flags.val & BR_BCAST_FLOOD ? BC_FFP(BIT(port)) : 0); |
| 301 | ++ |
| 302 | +++ if (flags.mask & BR_ISOLATED) { |
| 303 | +++ struct dsa_port *dp = dsa_to_port(ds, port); |
| 304 | +++ struct net_device *bridge_dev = dp->bridge_dev; |
| 305 | +++ |
| 306 | +++ priv->ports[port].isolated = !!(flags.val & BR_ISOLATED); |
| 307 | +++ |
| 308 | +++ mutex_lock(&priv->reg_mutex); |
| 309 | +++ mt7530_update_port_member(priv, port, bridge_dev, true); |
| 310 | +++ mutex_unlock(&priv->reg_mutex); |
| 311 | +++ } |
| 312 | +++ |
| 313 | ++ return 0; |
| 314 | ++ } |
| 315 | ++ |
| 316 | ++--- a/drivers/net/dsa/mt7530.h |
| 317 | +++++ b/drivers/net/dsa/mt7530.h |
| 318 | ++@@ -706,6 +706,7 @@ struct mt7530_fdb { |
| 319 | ++ */ |
| 320 | ++ struct mt7530_port { |
| 321 | ++ bool enable; |
| 322 | +++ bool isolated; |
| 323 | ++ u32 pm; |
| 324 | ++ u16 pvid; |
| 325 | ++ struct phylink_pcs *sgmii_pcs; |
0 commit comments