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