Merge tag 'arm-late-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-microblaze.git] / net / bridge / br_mrp_netlink.c
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
9 static 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
22 static const struct nla_policy
23 br_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
31 static 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
69 static const struct nla_policy
70 br_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
75 static 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
98 static const struct nla_policy
99 br_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
104 static 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
127 static const struct nla_policy
128 br_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
134 static 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
161 static const struct nla_policy
162 br_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
168 static 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
195 static const struct nla_policy
196 br_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
205 static 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
241 static const struct nla_policy
242 br_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
248 static 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
275 static const struct nla_policy
276 br_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
284 static 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
315 static const struct nla_policy
316 br_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
324 static 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
356 int 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
447 int 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
520 nla_put_failure:
521         nla_nest_cancel(skb, tb);
522
523 nla_info_failure:
524         nla_nest_cancel(skb, mrp_tb);
525
526         return -EMSGSIZE;
527 }
528
529 int 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
547 out:
548         return err;
549 }
550
551 int 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
569 out:
570         return err;
571 }