1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Bridge Multiple Spanning Tree Support 4 * 5 * Authors: 6 * Tobias Waldekranz <tobias@waldekranz.com> 7 */ 8 9 #include <linux/kernel.h> 10 #include <net/switchdev.h> 11 12 #include "br_private.h" 13 14 DEFINE_STATIC_KEY_FALSE(br_mst_used); 15 16 bool br_mst_enabled(const struct net_device *dev) 17 { 18 if (!netif_is_bridge_master(dev)) 19 return false; 20 21 return br_opt_get(netdev_priv(dev), BROPT_MST_ENABLED); 22 } 23 EXPORT_SYMBOL_GPL(br_mst_enabled); 24 25 int br_mst_get_info(const struct net_device *dev, u16 msti, unsigned long *vids) 26 { 27 const struct net_bridge_vlan_group *vg; 28 const struct net_bridge_vlan *v; 29 const struct net_bridge *br; 30 31 ASSERT_RTNL(); 32 33 if (!netif_is_bridge_master(dev)) 34 return -EINVAL; 35 36 br = netdev_priv(dev); 37 if (!br_opt_get(br, BROPT_MST_ENABLED)) 38 return -EINVAL; 39 40 vg = br_vlan_group(br); 41 42 list_for_each_entry(v, &vg->vlan_list, vlist) { 43 if (v->msti == msti) 44 __set_bit(v->vid, vids); 45 } 46 47 return 0; 48 } 49 EXPORT_SYMBOL_GPL(br_mst_get_info); 50 51 int br_mst_get_state(const struct net_device *dev, u16 msti, u8 *state) 52 { 53 const struct net_bridge_port *p = NULL; 54 const struct net_bridge_vlan_group *vg; 55 const struct net_bridge_vlan *v; 56 57 ASSERT_RTNL(); 58 59 p = br_port_get_check_rtnl(dev); 60 if (!p || !br_opt_get(p->br, BROPT_MST_ENABLED)) 61 return -EINVAL; 62 63 vg = nbp_vlan_group(p); 64 65 list_for_each_entry(v, &vg->vlan_list, vlist) { 66 if (v->brvlan->msti == msti) { 67 *state = v->state; 68 return 0; 69 } 70 } 71 72 return -ENOENT; 73 } 74 EXPORT_SYMBOL_GPL(br_mst_get_state); 75 76 static void br_mst_vlan_set_state(struct net_bridge_port *p, struct net_bridge_vlan *v, 77 u8 state) 78 { 79 struct net_bridge_vlan_group *vg = nbp_vlan_group(p); 80 81 if (br_vlan_get_state(v) == state) 82 return; 83 84 br_vlan_set_state(v, state); 85 86 if (v->vid == vg->pvid) 87 br_vlan_set_pvid_state(vg, state); 88 } 89 90 int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state, 91 struct netlink_ext_ack *extack) 92 { 93 struct switchdev_attr attr = { 94 .id = SWITCHDEV_ATTR_ID_PORT_MST_STATE, 95 .orig_dev = p->dev, 96 .u.mst_state = { 97 .msti = msti, 98 .state = state, 99 }, 100 }; 101 struct net_bridge_vlan_group *vg; 102 struct net_bridge_vlan *v; 103 int err = 0; 104 105 rcu_read_lock(); 106 vg = nbp_vlan_group(p); 107 if (!vg) 108 goto out; 109 110 /* MSTI 0 (CST) state changes are notified via the regular 111 * SWITCHDEV_ATTR_ID_PORT_STP_STATE. 112 */ 113 if (msti) { 114 err = switchdev_port_attr_set(p->dev, &attr, extack); 115 if (err && err != -EOPNOTSUPP) 116 goto out; 117 } 118 119 err = 0; 120 list_for_each_entry_rcu(v, &vg->vlan_list, vlist) { 121 if (v->brvlan->msti != msti) 122 continue; 123 124 br_mst_vlan_set_state(p, v, state); 125 } 126 127 out: 128 rcu_read_unlock(); 129 return err; 130 } 131 132 static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti) 133 { 134 struct net_bridge_vlan_group *vg = nbp_vlan_group(pv->port); 135 struct net_bridge_vlan *v; 136 137 list_for_each_entry(v, &vg->vlan_list, vlist) { 138 /* If this port already has a defined state in this 139 * MSTI (through some other VLAN membership), inherit 140 * it. 141 */ 142 if (v != pv && v->brvlan->msti == msti) { 143 br_mst_vlan_set_state(pv->port, pv, v->state); 144 return; 145 } 146 } 147 148 /* Otherwise, start out in a new MSTI with all ports disabled. */ 149 return br_mst_vlan_set_state(pv->port, pv, BR_STATE_DISABLED); 150 } 151 152 int br_mst_vlan_set_msti(struct net_bridge_vlan *mv, u16 msti) 153 { 154 struct switchdev_attr attr = { 155 .id = SWITCHDEV_ATTR_ID_VLAN_MSTI, 156 .orig_dev = mv->br->dev, 157 .u.vlan_msti = { 158 .vid = mv->vid, 159 .msti = msti, 160 }, 161 }; 162 struct net_bridge_vlan_group *vg; 163 struct net_bridge_vlan *pv; 164 struct net_bridge_port *p; 165 int err; 166 167 if (mv->msti == msti) 168 return 0; 169 170 err = switchdev_port_attr_set(mv->br->dev, &attr, NULL); 171 if (err && err != -EOPNOTSUPP) 172 return err; 173 174 mv->msti = msti; 175 176 list_for_each_entry(p, &mv->br->port_list, list) { 177 vg = nbp_vlan_group(p); 178 179 pv = br_vlan_find(vg, mv->vid); 180 if (pv) 181 br_mst_vlan_sync_state(pv, msti); 182 } 183 184 return 0; 185 } 186 187 void br_mst_vlan_init_state(struct net_bridge_vlan *v) 188 { 189 /* VLANs always start out in MSTI 0 (CST) */ 190 v->msti = 0; 191 192 if (br_vlan_is_master(v)) 193 v->state = BR_STATE_FORWARDING; 194 else 195 v->state = v->port->state; 196 } 197 198 int br_mst_set_enabled(struct net_bridge *br, bool on, 199 struct netlink_ext_ack *extack) 200 { 201 struct switchdev_attr attr = { 202 .id = SWITCHDEV_ATTR_ID_BRIDGE_MST, 203 .orig_dev = br->dev, 204 .u.mst = on, 205 }; 206 struct net_bridge_vlan_group *vg; 207 struct net_bridge_port *p; 208 int err; 209 210 list_for_each_entry(p, &br->port_list, list) { 211 vg = nbp_vlan_group(p); 212 213 if (!vg->num_vlans) 214 continue; 215 216 NL_SET_ERR_MSG(extack, 217 "MST mode can't be changed while VLANs exist"); 218 return -EBUSY; 219 } 220 221 if (br_opt_get(br, BROPT_MST_ENABLED) == on) 222 return 0; 223 224 err = switchdev_port_attr_set(br->dev, &attr, extack); 225 if (err && err != -EOPNOTSUPP) 226 return err; 227 228 if (on) 229 static_branch_enable(&br_mst_used); 230 else 231 static_branch_disable(&br_mst_used); 232 233 br_opt_toggle(br, BROPT_MST_ENABLED, on); 234 return 0; 235 } 236 237 size_t br_mst_info_size(const struct net_bridge_vlan_group *vg) 238 { 239 DECLARE_BITMAP(seen, VLAN_N_VID) = { 0 }; 240 const struct net_bridge_vlan *v; 241 size_t sz; 242 243 /* IFLA_BRIDGE_MST */ 244 sz = nla_total_size(0); 245 246 list_for_each_entry_rcu(v, &vg->vlan_list, vlist) { 247 if (test_bit(v->brvlan->msti, seen)) 248 continue; 249 250 /* IFLA_BRIDGE_MST_ENTRY */ 251 sz += nla_total_size(0) + 252 /* IFLA_BRIDGE_MST_ENTRY_MSTI */ 253 nla_total_size(sizeof(u16)) + 254 /* IFLA_BRIDGE_MST_ENTRY_STATE */ 255 nla_total_size(sizeof(u8)); 256 257 __set_bit(v->brvlan->msti, seen); 258 } 259 260 return sz; 261 } 262 263 int br_mst_fill_info(struct sk_buff *skb, 264 const struct net_bridge_vlan_group *vg) 265 { 266 DECLARE_BITMAP(seen, VLAN_N_VID) = { 0 }; 267 const struct net_bridge_vlan *v; 268 struct nlattr *nest; 269 int err = 0; 270 271 list_for_each_entry(v, &vg->vlan_list, vlist) { 272 if (test_bit(v->brvlan->msti, seen)) 273 continue; 274 275 nest = nla_nest_start_noflag(skb, IFLA_BRIDGE_MST_ENTRY); 276 if (!nest || 277 nla_put_u16(skb, IFLA_BRIDGE_MST_ENTRY_MSTI, v->brvlan->msti) || 278 nla_put_u8(skb, IFLA_BRIDGE_MST_ENTRY_STATE, v->state)) { 279 err = -EMSGSIZE; 280 break; 281 } 282 nla_nest_end(skb, nest); 283 284 __set_bit(v->brvlan->msti, seen); 285 } 286 287 return err; 288 } 289 290 static const struct nla_policy br_mst_nl_policy[IFLA_BRIDGE_MST_ENTRY_MAX + 1] = { 291 [IFLA_BRIDGE_MST_ENTRY_MSTI] = NLA_POLICY_RANGE(NLA_U16, 292 1, /* 0 reserved for CST */ 293 VLAN_N_VID - 1), 294 [IFLA_BRIDGE_MST_ENTRY_STATE] = NLA_POLICY_RANGE(NLA_U8, 295 BR_STATE_DISABLED, 296 BR_STATE_BLOCKING), 297 }; 298 299 static int br_mst_process_one(struct net_bridge_port *p, 300 const struct nlattr *attr, 301 struct netlink_ext_ack *extack) 302 { 303 struct nlattr *tb[IFLA_BRIDGE_MST_ENTRY_MAX + 1]; 304 u16 msti; 305 u8 state; 306 int err; 307 308 err = nla_parse_nested(tb, IFLA_BRIDGE_MST_ENTRY_MAX, attr, 309 br_mst_nl_policy, extack); 310 if (err) 311 return err; 312 313 if (!tb[IFLA_BRIDGE_MST_ENTRY_MSTI]) { 314 NL_SET_ERR_MSG_MOD(extack, "MSTI not specified"); 315 return -EINVAL; 316 } 317 318 if (!tb[IFLA_BRIDGE_MST_ENTRY_STATE]) { 319 NL_SET_ERR_MSG_MOD(extack, "State not specified"); 320 return -EINVAL; 321 } 322 323 msti = nla_get_u16(tb[IFLA_BRIDGE_MST_ENTRY_MSTI]); 324 state = nla_get_u8(tb[IFLA_BRIDGE_MST_ENTRY_STATE]); 325 326 return br_mst_set_state(p, msti, state, extack); 327 } 328 329 int br_mst_process(struct net_bridge_port *p, const struct nlattr *mst_attr, 330 struct netlink_ext_ack *extack) 331 { 332 struct nlattr *attr; 333 int err, msts = 0; 334 int rem; 335 336 if (!br_opt_get(p->br, BROPT_MST_ENABLED)) { 337 NL_SET_ERR_MSG_MOD(extack, "Can't modify MST state when MST is disabled"); 338 return -EBUSY; 339 } 340 341 nla_for_each_nested(attr, mst_attr, rem) { 342 switch (nla_type(attr)) { 343 case IFLA_BRIDGE_MST_ENTRY: 344 err = br_mst_process_one(p, attr, extack); 345 break; 346 default: 347 continue; 348 } 349 350 msts++; 351 if (err) 352 break; 353 } 354 355 if (!msts) { 356 NL_SET_ERR_MSG_MOD(extack, "Found no MST entries to process"); 357 err = -EINVAL; 358 } 359 360 return err; 361 } 362