xref: /linux/net/bridge/br_mst.c (revision 14c5eb685cdefbd32e73d2723071ecbd8effbce9)
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 	/* 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 
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 
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 
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 
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 
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 
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 
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 
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