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