Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2
  3#include <net/genetlink.h>
  4
  5#include <uapi/linux/mrp_bridge.h>
  6#include "br_private.h"
  7#include "br_private_mrp.h"
  8
  9static const struct nla_policy br_mrp_policy[IFLA_BRIDGE_MRP_MAX + 1] = {
 10	[IFLA_BRIDGE_MRP_UNSPEC]	= { .type = NLA_REJECT },
 11	[IFLA_BRIDGE_MRP_INSTANCE]	= { .type = NLA_NESTED },
 12	[IFLA_BRIDGE_MRP_PORT_STATE]	= { .type = NLA_NESTED },
 13	[IFLA_BRIDGE_MRP_PORT_ROLE]	= { .type = NLA_NESTED },
 14	[IFLA_BRIDGE_MRP_RING_STATE]	= { .type = NLA_NESTED },
 15	[IFLA_BRIDGE_MRP_RING_ROLE]	= { .type = NLA_NESTED },
 16	[IFLA_BRIDGE_MRP_START_TEST]	= { .type = NLA_NESTED },
 17	[IFLA_BRIDGE_MRP_IN_ROLE]	= { .type = NLA_NESTED },
 18	[IFLA_BRIDGE_MRP_IN_STATE]	= { .type = NLA_NESTED },
 19	[IFLA_BRIDGE_MRP_START_IN_TEST]	= { .type = NLA_NESTED },
 20};
 21
 22static const struct nla_policy
 23br_mrp_instance_policy[IFLA_BRIDGE_MRP_INSTANCE_MAX + 1] = {
 24	[IFLA_BRIDGE_MRP_INSTANCE_UNSPEC]	= { .type = NLA_REJECT },
 25	[IFLA_BRIDGE_MRP_INSTANCE_RING_ID]	= { .type = NLA_U32 },
 26	[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX]	= { .type = NLA_U32 },
 27	[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]	= { .type = NLA_U32 },
 28	[IFLA_BRIDGE_MRP_INSTANCE_PRIO]		= { .type = NLA_U16 },
 29};
 30
 31static int br_mrp_instance_parse(struct net_bridge *br, struct nlattr *attr,
 32				 int cmd, struct netlink_ext_ack *extack)
 33{
 34	struct nlattr *tb[IFLA_BRIDGE_MRP_INSTANCE_MAX + 1];
 35	struct br_mrp_instance inst;
 36	int err;
 37
 38	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_INSTANCE_MAX, attr,
 39			       br_mrp_instance_policy, extack);
 40	if (err)
 41		return err;
 42
 43	if (!tb[IFLA_BRIDGE_MRP_INSTANCE_RING_ID] ||
 44	    !tb[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX] ||
 45	    !tb[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]) {
 46		NL_SET_ERR_MSG_MOD(extack,
 47				   "Missing attribute: RING_ID or P_IFINDEX or S_IFINDEX");
 48		return -EINVAL;
 49	}
 50
 51	memset(&inst, 0, sizeof(inst));
 52
 53	inst.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_RING_ID]);
 54	inst.p_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX]);
 55	inst.s_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]);
 56	inst.prio = MRP_DEFAULT_PRIO;
 57
 58	if (tb[IFLA_BRIDGE_MRP_INSTANCE_PRIO])
 59		inst.prio = nla_get_u16(tb[IFLA_BRIDGE_MRP_INSTANCE_PRIO]);
 60
 61	if (cmd == RTM_SETLINK)
 62		return br_mrp_add(br, &inst);
 63	else
 64		return br_mrp_del(br, &inst);
 65
 66	return 0;
 67}
 68
 69static const struct nla_policy
 70br_mrp_port_state_policy[IFLA_BRIDGE_MRP_PORT_STATE_MAX + 1] = {
 71	[IFLA_BRIDGE_MRP_PORT_STATE_UNSPEC]	= { .type = NLA_REJECT },
 72	[IFLA_BRIDGE_MRP_PORT_STATE_STATE]	= { .type = NLA_U32 },
 73};
 74
 75static int br_mrp_port_state_parse(struct net_bridge_port *p,
 76				   struct nlattr *attr,
 77				   struct netlink_ext_ack *extack)
 78{
 79	struct nlattr *tb[IFLA_BRIDGE_MRP_PORT_STATE_MAX + 1];
 80	enum br_mrp_port_state_type state;
 81	int err;
 82
 83	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_PORT_STATE_MAX, attr,
 84			       br_mrp_port_state_policy, extack);
 85	if (err)
 86		return err;
 87
 88	if (!tb[IFLA_BRIDGE_MRP_PORT_STATE_STATE]) {
 89		NL_SET_ERR_MSG_MOD(extack, "Missing attribute: STATE");
 90		return -EINVAL;
 91	}
 92
 93	state = nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_STATE_STATE]);
 94
 95	return br_mrp_set_port_state(p, state);
 96}
 97
 98static const struct nla_policy
 99br_mrp_port_role_policy[IFLA_BRIDGE_MRP_PORT_ROLE_MAX + 1] = {
100	[IFLA_BRIDGE_MRP_PORT_ROLE_UNSPEC]	= { .type = NLA_REJECT },
101	[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]	= { .type = NLA_U32 },
102};
103
104static int br_mrp_port_role_parse(struct net_bridge_port *p,
105				  struct nlattr *attr,
106				  struct netlink_ext_ack *extack)
107{
108	struct nlattr *tb[IFLA_BRIDGE_MRP_PORT_ROLE_MAX + 1];
109	enum br_mrp_port_role_type role;
110	int err;
111
112	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_PORT_ROLE_MAX, attr,
113			       br_mrp_port_role_policy, extack);
114	if (err)
115		return err;
116
117	if (!tb[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]) {
118		NL_SET_ERR_MSG_MOD(extack, "Missing attribute: ROLE");
119		return -EINVAL;
120	}
121
122	role = nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]);
123
124	return br_mrp_set_port_role(p, role);
125}
126
127static const struct nla_policy
128br_mrp_ring_state_policy[IFLA_BRIDGE_MRP_RING_STATE_MAX + 1] = {
129	[IFLA_BRIDGE_MRP_RING_STATE_UNSPEC]	= { .type = NLA_REJECT },
130	[IFLA_BRIDGE_MRP_RING_STATE_RING_ID]	= { .type = NLA_U32 },
131	[IFLA_BRIDGE_MRP_RING_STATE_STATE]	= { .type = NLA_U32 },
132};
133
134static int br_mrp_ring_state_parse(struct net_bridge *br, struct nlattr *attr,
135				   struct netlink_ext_ack *extack)
136{
137	struct nlattr *tb[IFLA_BRIDGE_MRP_RING_STATE_MAX + 1];
138	struct br_mrp_ring_state state;
139	int err;
140
141	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_RING_STATE_MAX, attr,
142			       br_mrp_ring_state_policy, extack);
143	if (err)
144		return err;
145
146	if (!tb[IFLA_BRIDGE_MRP_RING_STATE_RING_ID] ||
147	    !tb[IFLA_BRIDGE_MRP_RING_STATE_STATE]) {
148		NL_SET_ERR_MSG_MOD(extack,
149				   "Missing attribute: RING_ID or STATE");
150		return -EINVAL;
151	}
152
153	memset(&state, 0x0, sizeof(state));
154
155	state.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_STATE_RING_ID]);
156	state.ring_state = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_STATE_STATE]);
157
158	return br_mrp_set_ring_state(br, &state);
159}
160
161static const struct nla_policy
162br_mrp_ring_role_policy[IFLA_BRIDGE_MRP_RING_ROLE_MAX + 1] = {
163	[IFLA_BRIDGE_MRP_RING_ROLE_UNSPEC]	= { .type = NLA_REJECT },
164	[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID]	= { .type = NLA_U32 },
165	[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]	= { .type = NLA_U32 },
166};
167
168static int br_mrp_ring_role_parse(struct net_bridge *br, struct nlattr *attr,
169				  struct netlink_ext_ack *extack)
170{
171	struct nlattr *tb[IFLA_BRIDGE_MRP_RING_ROLE_MAX + 1];
172	struct br_mrp_ring_role role;
173	int err;
174
175	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_RING_ROLE_MAX, attr,
176			       br_mrp_ring_role_policy, extack);
177	if (err)
178		return err;
179
180	if (!tb[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID] ||
181	    !tb[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]) {
182		NL_SET_ERR_MSG_MOD(extack,
183				   "Missing attribute: RING_ID or ROLE");
184		return -EINVAL;
185	}
186
187	memset(&role, 0x0, sizeof(role));
188
189	role.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID]);
190	role.ring_role = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]);
191
192	return br_mrp_set_ring_role(br, &role);
193}
194
195static const struct nla_policy
196br_mrp_start_test_policy[IFLA_BRIDGE_MRP_START_TEST_MAX + 1] = {
197	[IFLA_BRIDGE_MRP_START_TEST_UNSPEC]	= { .type = NLA_REJECT },
198	[IFLA_BRIDGE_MRP_START_TEST_RING_ID]	= { .type = NLA_U32 },
199	[IFLA_BRIDGE_MRP_START_TEST_INTERVAL]	= { .type = NLA_U32 },
200	[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS]	= { .type = NLA_U32 },
201	[IFLA_BRIDGE_MRP_START_TEST_PERIOD]	= { .type = NLA_U32 },
202	[IFLA_BRIDGE_MRP_START_TEST_MONITOR]	= { .type = NLA_U32 },
203};
204
205static int br_mrp_start_test_parse(struct net_bridge *br, struct nlattr *attr,
206				   struct netlink_ext_ack *extack)
207{
208	struct nlattr *tb[IFLA_BRIDGE_MRP_START_TEST_MAX + 1];
209	struct br_mrp_start_test test;
210	int err;
211
212	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_START_TEST_MAX, attr,
213			       br_mrp_start_test_policy, extack);
214	if (err)
215		return err;
216
217	if (!tb[IFLA_BRIDGE_MRP_START_TEST_RING_ID] ||
218	    !tb[IFLA_BRIDGE_MRP_START_TEST_INTERVAL] ||
219	    !tb[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS] ||
220	    !tb[IFLA_BRIDGE_MRP_START_TEST_PERIOD]) {
221		NL_SET_ERR_MSG_MOD(extack,
222				   "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
223		return -EINVAL;
224	}
225
226	memset(&test, 0x0, sizeof(test));
227
228	test.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_RING_ID]);
229	test.interval = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_INTERVAL]);
230	test.max_miss = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS]);
231	test.period = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_PERIOD]);
232	test.monitor = false;
233
234	if (tb[IFLA_BRIDGE_MRP_START_TEST_MONITOR])
235		test.monitor =
236			nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_MONITOR]);
237
238	return br_mrp_start_test(br, &test);
239}
240
241static const struct nla_policy
242br_mrp_in_state_policy[IFLA_BRIDGE_MRP_IN_STATE_MAX + 1] = {
243	[IFLA_BRIDGE_MRP_IN_STATE_UNSPEC]	= { .type = NLA_REJECT },
244	[IFLA_BRIDGE_MRP_IN_STATE_IN_ID]	= { .type = NLA_U32 },
245	[IFLA_BRIDGE_MRP_IN_STATE_STATE]	= { .type = NLA_U32 },
246};
247
248static int br_mrp_in_state_parse(struct net_bridge *br, struct nlattr *attr,
249				 struct netlink_ext_ack *extack)
250{
251	struct nlattr *tb[IFLA_BRIDGE_MRP_IN_STATE_MAX + 1];
252	struct br_mrp_in_state state;
253	int err;
254
255	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_IN_STATE_MAX, attr,
256			       br_mrp_in_state_policy, extack);
257	if (err)
258		return err;
259
260	if (!tb[IFLA_BRIDGE_MRP_IN_STATE_IN_ID] ||
261	    !tb[IFLA_BRIDGE_MRP_IN_STATE_STATE]) {
262		NL_SET_ERR_MSG_MOD(extack,
263				   "Missing attribute: IN_ID or STATE");
264		return -EINVAL;
265	}
266
267	memset(&state, 0x0, sizeof(state));
268
269	state.in_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_STATE_IN_ID]);
270	state.in_state = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_STATE_STATE]);
271
272	return br_mrp_set_in_state(br, &state);
273}
274
275static const struct nla_policy
276br_mrp_in_role_policy[IFLA_BRIDGE_MRP_IN_ROLE_MAX + 1] = {
277	[IFLA_BRIDGE_MRP_IN_ROLE_UNSPEC]	= { .type = NLA_REJECT },
278	[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID]	= { .type = NLA_U32 },
279	[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID]		= { .type = NLA_U16 },
280	[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]		= { .type = NLA_U32 },
281	[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX]	= { .type = NLA_U32 },
282};
283
284static int br_mrp_in_role_parse(struct net_bridge *br, struct nlattr *attr,
285				struct netlink_ext_ack *extack)
286{
287	struct nlattr *tb[IFLA_BRIDGE_MRP_IN_ROLE_MAX + 1];
288	struct br_mrp_in_role role;
289	int err;
290
291	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_IN_ROLE_MAX, attr,
292			       br_mrp_in_role_policy, extack);
293	if (err)
294		return err;
295
296	if (!tb[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID] ||
297	    !tb[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID] ||
298	    !tb[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX] ||
299	    !tb[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]) {
300		NL_SET_ERR_MSG_MOD(extack,
301				   "Missing attribute: RING_ID or ROLE or IN_ID or I_IFINDEX");
302		return -EINVAL;
303	}
304
305	memset(&role, 0x0, sizeof(role));
306
307	role.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID]);
308	role.in_id = nla_get_u16(tb[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID]);
309	role.i_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX]);
310	role.in_role = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]);
311
312	return br_mrp_set_in_role(br, &role);
313}
314
315static const struct nla_policy
316br_mrp_start_in_test_policy[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1] = {
317	[IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC]	= { .type = NLA_REJECT },
318	[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID]	= { .type = NLA_U32 },
319	[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL]	= { .type = NLA_U32 },
320	[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS]	= { .type = NLA_U32 },
321	[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]	= { .type = NLA_U32 },
322};
323
324static int br_mrp_start_in_test_parse(struct net_bridge *br,
325				      struct nlattr *attr,
326				      struct netlink_ext_ack *extack)
327{
328	struct nlattr *tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1];
329	struct br_mrp_start_in_test test;
330	int err;
331
332	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_START_IN_TEST_MAX, attr,
333			       br_mrp_start_in_test_policy, extack);
334	if (err)
335		return err;
336
337	if (!tb[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID] ||
338	    !tb[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] ||
339	    !tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] ||
340	    !tb[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]) {
341		NL_SET_ERR_MSG_MOD(extack,
342				   "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
343		return -EINVAL;
344	}
345
346	memset(&test, 0x0, sizeof(test));
347
348	test.in_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID]);
349	test.interval = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL]);
350	test.max_miss = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS]);
351	test.period = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]);
352
353	return br_mrp_start_in_test(br, &test);
354}
355
356int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
357		 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
358{
359	struct nlattr *tb[IFLA_BRIDGE_MRP_MAX + 1];
360	int err;
361
362	/* When this function is called for a port then the br pointer is
363	 * invalid, therefor set the br to point correctly
364	 */
365	if (p)
366		br = p->br;
367
368	if (br->stp_enabled != BR_NO_STP) {
369		NL_SET_ERR_MSG_MOD(extack, "MRP can't be enabled if STP is already enabled");
370		return -EINVAL;
371	}
372
373	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_MAX, attr,
374			       br_mrp_policy, extack);
375	if (err)
376		return err;
377
378	if (tb[IFLA_BRIDGE_MRP_INSTANCE]) {
379		err = br_mrp_instance_parse(br, tb[IFLA_BRIDGE_MRP_INSTANCE],
380					    cmd, extack);
381		if (err)
382			return err;
383	}
384
385	if (tb[IFLA_BRIDGE_MRP_PORT_STATE]) {
386		err = br_mrp_port_state_parse(p, tb[IFLA_BRIDGE_MRP_PORT_STATE],
387					      extack);
388		if (err)
389			return err;
390	}
391
392	if (tb[IFLA_BRIDGE_MRP_PORT_ROLE]) {
393		err = br_mrp_port_role_parse(p, tb[IFLA_BRIDGE_MRP_PORT_ROLE],
394					     extack);
395		if (err)
396			return err;
397	}
398
399	if (tb[IFLA_BRIDGE_MRP_RING_STATE]) {
400		err = br_mrp_ring_state_parse(br,
401					      tb[IFLA_BRIDGE_MRP_RING_STATE],
402					      extack);
403		if (err)
404			return err;
405	}
406
407	if (tb[IFLA_BRIDGE_MRP_RING_ROLE]) {
408		err = br_mrp_ring_role_parse(br, tb[IFLA_BRIDGE_MRP_RING_ROLE],
409					     extack);
410		if (err)
411			return err;
412	}
413
414	if (tb[IFLA_BRIDGE_MRP_START_TEST]) {
415		err = br_mrp_start_test_parse(br,
416					      tb[IFLA_BRIDGE_MRP_START_TEST],
417					      extack);
418		if (err)
419			return err;
420	}
421
422	if (tb[IFLA_BRIDGE_MRP_IN_STATE]) {
423		err = br_mrp_in_state_parse(br, tb[IFLA_BRIDGE_MRP_IN_STATE],
424					    extack);
425		if (err)
426			return err;
427	}
428
429	if (tb[IFLA_BRIDGE_MRP_IN_ROLE]) {
430		err = br_mrp_in_role_parse(br, tb[IFLA_BRIDGE_MRP_IN_ROLE],
431					   extack);
432		if (err)
433			return err;
434	}
435
436	if (tb[IFLA_BRIDGE_MRP_START_IN_TEST]) {
437		err = br_mrp_start_in_test_parse(br,
438						 tb[IFLA_BRIDGE_MRP_START_IN_TEST],
439						 extack);
440		if (err)
441			return err;
442	}
443
444	return 0;
445}
446
447int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br)
448{
449	struct nlattr *tb, *mrp_tb;
450	struct br_mrp *mrp;
451
452	mrp_tb = nla_nest_start_noflag(skb, IFLA_BRIDGE_MRP);
453	if (!mrp_tb)
454		return -EMSGSIZE;
455
456	hlist_for_each_entry_rcu(mrp, &br->mrp_list, list) {
457		struct net_bridge_port *p;
458
459		tb = nla_nest_start_noflag(skb, IFLA_BRIDGE_MRP_INFO);
460		if (!tb)
461			goto nla_info_failure;
462
463		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_ID,
464				mrp->ring_id))
465			goto nla_put_failure;
466
467		p = rcu_dereference(mrp->p_port);
468		if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_P_IFINDEX,
469				     p->dev->ifindex))
470			goto nla_put_failure;
471
472		p = rcu_dereference(mrp->s_port);
473		if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_S_IFINDEX,
474				     p->dev->ifindex))
475			goto nla_put_failure;
476
477		p = rcu_dereference(mrp->i_port);
478		if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_I_IFINDEX,
479				     p->dev->ifindex))
480			goto nla_put_failure;
481
482		if (nla_put_u16(skb, IFLA_BRIDGE_MRP_INFO_PRIO,
483				mrp->prio))
484			goto nla_put_failure;
485		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_STATE,
486				mrp->ring_state))
487			goto nla_put_failure;
488		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_ROLE,
489				mrp->ring_role))
490			goto nla_put_failure;
491		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_INTERVAL,
492				mrp->test_interval))
493			goto nla_put_failure;
494		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_MAX_MISS,
495				mrp->test_max_miss))
496			goto nla_put_failure;
497		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_MONITOR,
498				mrp->test_monitor))
499			goto nla_put_failure;
500
501		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_STATE,
502				mrp->in_state))
503			goto nla_put_failure;
504		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_ROLE,
505				mrp->in_role))
506			goto nla_put_failure;
507		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_TEST_INTERVAL,
508				mrp->in_test_interval))
509			goto nla_put_failure;
510		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_TEST_MAX_MISS,
511				mrp->in_test_max_miss))
512			goto nla_put_failure;
513
514		nla_nest_end(skb, tb);
515	}
516	nla_nest_end(skb, mrp_tb);
517
518	return 0;
519
520nla_put_failure:
521	nla_nest_cancel(skb, tb);
522
523nla_info_failure:
524	nla_nest_cancel(skb, mrp_tb);
525
526	return -EMSGSIZE;
527}
528
529int br_mrp_ring_port_open(struct net_device *dev, u8 loc)
530{
531	struct net_bridge_port *p;
532	int err = 0;
533
534	p = br_port_get_rcu(dev);
535	if (!p) {
536		err = -EINVAL;
537		goto out;
538	}
539
540	if (loc)
541		p->flags |= BR_MRP_LOST_CONT;
542	else
543		p->flags &= ~BR_MRP_LOST_CONT;
544
545	br_ifinfo_notify(RTM_NEWLINK, NULL, p);
546
547out:
548	return err;
549}
550
551int br_mrp_in_port_open(struct net_device *dev, u8 loc)
552{
553	struct net_bridge_port *p;
554	int err = 0;
555
556	p = br_port_get_rcu(dev);
557	if (!p) {
558		err = -EINVAL;
559		goto out;
560	}
561
562	if (loc)
563		p->flags |= BR_MRP_LOST_IN_CONT;
564	else
565		p->flags &= ~BR_MRP_LOST_IN_CONT;
566
567	br_ifinfo_notify(RTM_NEWLINK, NULL, p);
568
569out:
570	return err;
571}