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 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
br_mst_vlan_sync_state(struct net_bridge_vlan * pv,u16 msti)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
br_mst_vlan_set_msti(struct net_bridge_vlan * mv,u16 msti)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
br_mst_vlan_init_state(struct net_bridge_vlan * v)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
br_mst_set_enabled(struct net_bridge * br,bool on,struct netlink_ext_ack * extack)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
br_mst_info_size(const struct net_bridge_vlan_group * vg)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
br_mst_fill_info(struct sk_buff * skb,const struct net_bridge_vlan_group * vg)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
br_mst_process_one(struct net_bridge_port * p,const struct nlattr * attr,struct netlink_ext_ack * extack)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
br_mst_process(struct net_bridge_port * p,const struct nlattr * mst_attr,struct netlink_ext_ack * extack)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