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