Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/bridge/br_mrp_netlink.c
26278 views
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
}
572
573