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