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