Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/bridge/br_cfm_netlink.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
#include <net/genetlink.h>
4
5
#include "br_private.h"
6
#include "br_private_cfm.h"
7
8
static const struct nla_policy
9
br_cfm_mep_create_policy[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1] = {
10
[IFLA_BRIDGE_CFM_MEP_CREATE_UNSPEC] = { .type = NLA_REJECT },
11
[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE] = { .type = NLA_U32 },
12
[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN] = { .type = NLA_U32 },
13
[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION] = { .type = NLA_U32 },
14
[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX] = { .type = NLA_U32 },
15
};
16
17
static const struct nla_policy
18
br_cfm_mep_delete_policy[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1] = {
19
[IFLA_BRIDGE_CFM_MEP_DELETE_UNSPEC] = { .type = NLA_REJECT },
20
[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE] = { .type = NLA_U32 },
21
};
22
23
static const struct nla_policy
24
br_cfm_mep_config_policy[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1] = {
25
[IFLA_BRIDGE_CFM_MEP_CONFIG_UNSPEC] = { .type = NLA_REJECT },
26
[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE] = { .type = NLA_U32 },
27
[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC] = NLA_POLICY_ETH_ADDR,
28
[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL] = NLA_POLICY_MAX(NLA_U32, 7),
29
[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID] = NLA_POLICY_MAX(NLA_U32, 0x1FFF),
30
};
31
32
static const struct nla_policy
33
br_cfm_cc_config_policy[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1] = {
34
[IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC] = { .type = NLA_REJECT },
35
[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE] = { .type = NLA_U32 },
36
[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE] = { .type = NLA_U32 },
37
[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = { .type = NLA_U32 },
38
[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID] = {
39
.type = NLA_BINARY, .len = CFM_MAID_LENGTH },
40
};
41
42
static const struct nla_policy
43
br_cfm_cc_peer_mep_policy[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1] = {
44
[IFLA_BRIDGE_CFM_CC_PEER_MEP_UNSPEC] = { .type = NLA_REJECT },
45
[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE] = { .type = NLA_U32 },
46
[IFLA_BRIDGE_CFM_CC_PEER_MEPID] = NLA_POLICY_MAX(NLA_U32, 0x1FFF),
47
};
48
49
static const struct nla_policy
50
br_cfm_cc_rdi_policy[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1] = {
51
[IFLA_BRIDGE_CFM_CC_RDI_UNSPEC] = { .type = NLA_REJECT },
52
[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE] = { .type = NLA_U32 },
53
[IFLA_BRIDGE_CFM_CC_RDI_RDI] = { .type = NLA_U32 },
54
};
55
56
static const struct nla_policy
57
br_cfm_cc_ccm_tx_policy[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1] = {
58
[IFLA_BRIDGE_CFM_CC_CCM_TX_UNSPEC] = { .type = NLA_REJECT },
59
[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE] = { .type = NLA_U32 },
60
[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC] = NLA_POLICY_ETH_ADDR,
61
[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE] = { .type = NLA_U32 },
62
[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD] = { .type = NLA_U32 },
63
[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV] = { .type = NLA_U32 },
64
[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE] = { .type = NLA_U8 },
65
[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV] = { .type = NLA_U32 },
66
[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE] = { .type = NLA_U8 },
67
};
68
69
static const struct nla_policy
70
br_cfm_policy[IFLA_BRIDGE_CFM_MAX + 1] = {
71
[IFLA_BRIDGE_CFM_UNSPEC] = { .type = NLA_REJECT },
72
[IFLA_BRIDGE_CFM_MEP_CREATE] =
73
NLA_POLICY_NESTED(br_cfm_mep_create_policy),
74
[IFLA_BRIDGE_CFM_MEP_DELETE] =
75
NLA_POLICY_NESTED(br_cfm_mep_delete_policy),
76
[IFLA_BRIDGE_CFM_MEP_CONFIG] =
77
NLA_POLICY_NESTED(br_cfm_mep_config_policy),
78
[IFLA_BRIDGE_CFM_CC_CONFIG] =
79
NLA_POLICY_NESTED(br_cfm_cc_config_policy),
80
[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD] =
81
NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy),
82
[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE] =
83
NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy),
84
[IFLA_BRIDGE_CFM_CC_RDI] =
85
NLA_POLICY_NESTED(br_cfm_cc_rdi_policy),
86
[IFLA_BRIDGE_CFM_CC_CCM_TX] =
87
NLA_POLICY_NESTED(br_cfm_cc_ccm_tx_policy),
88
};
89
90
static int br_mep_create_parse(struct net_bridge *br, struct nlattr *attr,
91
struct netlink_ext_ack *extack)
92
{
93
struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1];
94
struct br_cfm_mep_create create;
95
u32 instance;
96
int err;
97
98
err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CREATE_MAX, attr,
99
br_cfm_mep_create_policy, extack);
100
if (err)
101
return err;
102
103
if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]) {
104
NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
105
return -EINVAL;
106
}
107
if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]) {
108
NL_SET_ERR_MSG_MOD(extack, "Missing DOMAIN attribute");
109
return -EINVAL;
110
}
111
if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]) {
112
NL_SET_ERR_MSG_MOD(extack, "Missing DIRECTION attribute");
113
return -EINVAL;
114
}
115
if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]) {
116
NL_SET_ERR_MSG_MOD(extack, "Missing IFINDEX attribute");
117
return -EINVAL;
118
}
119
120
memset(&create, 0, sizeof(create));
121
122
instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]);
123
create.domain = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]);
124
create.direction = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]);
125
create.ifindex = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]);
126
127
return br_cfm_mep_create(br, instance, &create, extack);
128
}
129
130
static int br_mep_delete_parse(struct net_bridge *br, struct nlattr *attr,
131
struct netlink_ext_ack *extack)
132
{
133
struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1];
134
u32 instance;
135
int err;
136
137
err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_DELETE_MAX, attr,
138
br_cfm_mep_delete_policy, extack);
139
if (err)
140
return err;
141
142
if (!tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]) {
143
NL_SET_ERR_MSG_MOD(extack,
144
"Missing INSTANCE attribute");
145
return -EINVAL;
146
}
147
148
instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]);
149
150
return br_cfm_mep_delete(br, instance, extack);
151
}
152
153
static int br_mep_config_parse(struct net_bridge *br, struct nlattr *attr,
154
struct netlink_ext_ack *extack)
155
{
156
struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1];
157
struct br_cfm_mep_config config;
158
u32 instance;
159
int err;
160
161
err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CONFIG_MAX, attr,
162
br_cfm_mep_config_policy, extack);
163
if (err)
164
return err;
165
166
if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]) {
167
NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
168
return -EINVAL;
169
}
170
if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC]) {
171
NL_SET_ERR_MSG_MOD(extack, "Missing UNICAST_MAC attribute");
172
return -EINVAL;
173
}
174
if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]) {
175
NL_SET_ERR_MSG_MOD(extack, "Missing MDLEVEL attribute");
176
return -EINVAL;
177
}
178
if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]) {
179
NL_SET_ERR_MSG_MOD(extack, "Missing MEPID attribute");
180
return -EINVAL;
181
}
182
183
memset(&config, 0, sizeof(config));
184
185
instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]);
186
nla_memcpy(&config.unicast_mac.addr,
187
tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC],
188
sizeof(config.unicast_mac.addr));
189
config.mdlevel = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]);
190
config.mepid = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]);
191
192
return br_cfm_mep_config_set(br, instance, &config, extack);
193
}
194
195
static int br_cc_config_parse(struct net_bridge *br, struct nlattr *attr,
196
struct netlink_ext_ack *extack)
197
{
198
struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1];
199
struct br_cfm_cc_config config;
200
u32 instance;
201
int err;
202
203
err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CONFIG_MAX, attr,
204
br_cfm_cc_config_policy, extack);
205
if (err)
206
return err;
207
208
if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]) {
209
NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
210
return -EINVAL;
211
}
212
if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]) {
213
NL_SET_ERR_MSG_MOD(extack, "Missing ENABLE attribute");
214
return -EINVAL;
215
}
216
if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]) {
217
NL_SET_ERR_MSG_MOD(extack, "Missing INTERVAL attribute");
218
return -EINVAL;
219
}
220
if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]) {
221
NL_SET_ERR_MSG_MOD(extack, "Missing MAID attribute");
222
return -EINVAL;
223
}
224
225
memset(&config, 0, sizeof(config));
226
227
instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]);
228
config.enable = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]);
229
config.exp_interval = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]);
230
nla_memcpy(&config.exp_maid.data, tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID],
231
sizeof(config.exp_maid.data));
232
233
return br_cfm_cc_config_set(br, instance, &config, extack);
234
}
235
236
static int br_cc_peer_mep_add_parse(struct net_bridge *br, struct nlattr *attr,
237
struct netlink_ext_ack *extack)
238
{
239
struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
240
u32 instance, peer_mep_id;
241
int err;
242
243
err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr,
244
br_cfm_cc_peer_mep_policy, extack);
245
if (err)
246
return err;
247
248
if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
249
NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
250
return -EINVAL;
251
}
252
if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
253
NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
254
return -EINVAL;
255
}
256
257
instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]);
258
peer_mep_id = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]);
259
260
return br_cfm_cc_peer_mep_add(br, instance, peer_mep_id, extack);
261
}
262
263
static int br_cc_peer_mep_remove_parse(struct net_bridge *br, struct nlattr *attr,
264
struct netlink_ext_ack *extack)
265
{
266
struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
267
u32 instance, peer_mep_id;
268
int err;
269
270
err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr,
271
br_cfm_cc_peer_mep_policy, extack);
272
if (err)
273
return err;
274
275
if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
276
NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
277
return -EINVAL;
278
}
279
if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
280
NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
281
return -EINVAL;
282
}
283
284
instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]);
285
peer_mep_id = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]);
286
287
return br_cfm_cc_peer_mep_remove(br, instance, peer_mep_id, extack);
288
}
289
290
static int br_cc_rdi_parse(struct net_bridge *br, struct nlattr *attr,
291
struct netlink_ext_ack *extack)
292
{
293
struct nlattr *tb[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1];
294
u32 instance, rdi;
295
int err;
296
297
err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_RDI_MAX, attr,
298
br_cfm_cc_rdi_policy, extack);
299
if (err)
300
return err;
301
302
if (!tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]) {
303
NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
304
return -EINVAL;
305
}
306
if (!tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]) {
307
NL_SET_ERR_MSG_MOD(extack, "Missing RDI attribute");
308
return -EINVAL;
309
}
310
311
instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]);
312
rdi = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]);
313
314
return br_cfm_cc_rdi_set(br, instance, rdi, extack);
315
}
316
317
static int br_cc_ccm_tx_parse(struct net_bridge *br, struct nlattr *attr,
318
struct netlink_ext_ack *extack)
319
{
320
struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1];
321
struct br_cfm_cc_ccm_tx_info tx_info;
322
u32 instance;
323
int err;
324
325
err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CCM_TX_MAX, attr,
326
br_cfm_cc_ccm_tx_policy, extack);
327
if (err)
328
return err;
329
330
if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]) {
331
NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
332
return -EINVAL;
333
}
334
if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]) {
335
NL_SET_ERR_MSG_MOD(extack, "Missing DMAC attribute");
336
return -EINVAL;
337
}
338
if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]) {
339
NL_SET_ERR_MSG_MOD(extack, "Missing SEQ_NO_UPDATE attribute");
340
return -EINVAL;
341
}
342
if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]) {
343
NL_SET_ERR_MSG_MOD(extack, "Missing PERIOD attribute");
344
return -EINVAL;
345
}
346
if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]) {
347
NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV attribute");
348
return -EINVAL;
349
}
350
if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]) {
351
NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV_VALUE attribute");
352
return -EINVAL;
353
}
354
if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]) {
355
NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV attribute");
356
return -EINVAL;
357
}
358
if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]) {
359
NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV_VALUE attribute");
360
return -EINVAL;
361
}
362
363
memset(&tx_info, 0, sizeof(tx_info));
364
365
instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]);
366
nla_memcpy(&tx_info.dmac.addr,
367
tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC],
368
sizeof(tx_info.dmac.addr));
369
tx_info.seq_no_update = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]);
370
tx_info.period = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]);
371
tx_info.if_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]);
372
tx_info.if_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]);
373
tx_info.port_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]);
374
tx_info.port_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]);
375
376
return br_cfm_cc_ccm_tx(br, instance, &tx_info, extack);
377
}
378
379
int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,
380
struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
381
{
382
struct nlattr *tb[IFLA_BRIDGE_CFM_MAX + 1];
383
int err;
384
385
/* When this function is called for a port then the br pointer is
386
* invalid, therefor set the br to point correctly
387
*/
388
if (p)
389
br = p->br;
390
391
err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MAX, attr,
392
br_cfm_policy, extack);
393
if (err)
394
return err;
395
396
if (tb[IFLA_BRIDGE_CFM_MEP_CREATE]) {
397
err = br_mep_create_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CREATE],
398
extack);
399
if (err)
400
return err;
401
}
402
403
if (tb[IFLA_BRIDGE_CFM_MEP_DELETE]) {
404
err = br_mep_delete_parse(br, tb[IFLA_BRIDGE_CFM_MEP_DELETE],
405
extack);
406
if (err)
407
return err;
408
}
409
410
if (tb[IFLA_BRIDGE_CFM_MEP_CONFIG]) {
411
err = br_mep_config_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CONFIG],
412
extack);
413
if (err)
414
return err;
415
}
416
417
if (tb[IFLA_BRIDGE_CFM_CC_CONFIG]) {
418
err = br_cc_config_parse(br, tb[IFLA_BRIDGE_CFM_CC_CONFIG],
419
extack);
420
if (err)
421
return err;
422
}
423
424
if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]) {
425
err = br_cc_peer_mep_add_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD],
426
extack);
427
if (err)
428
return err;
429
}
430
431
if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]) {
432
err = br_cc_peer_mep_remove_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE],
433
extack);
434
if (err)
435
return err;
436
}
437
438
if (tb[IFLA_BRIDGE_CFM_CC_RDI]) {
439
err = br_cc_rdi_parse(br, tb[IFLA_BRIDGE_CFM_CC_RDI],
440
extack);
441
if (err)
442
return err;
443
}
444
445
if (tb[IFLA_BRIDGE_CFM_CC_CCM_TX]) {
446
err = br_cc_ccm_tx_parse(br, tb[IFLA_BRIDGE_CFM_CC_CCM_TX],
447
extack);
448
if (err)
449
return err;
450
}
451
452
return 0;
453
}
454
455
int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br)
456
{
457
struct br_cfm_peer_mep *peer_mep;
458
struct br_cfm_mep *mep;
459
struct nlattr *tb;
460
461
hlist_for_each_entry_rcu(mep, &br->mep_list, head) {
462
tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INFO);
463
if (!tb)
464
goto nla_info_failure;
465
466
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE,
467
mep->instance))
468
goto nla_put_failure;
469
470
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN,
471
mep->create.domain))
472
goto nla_put_failure;
473
474
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION,
475
mep->create.direction))
476
goto nla_put_failure;
477
478
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX,
479
mep->create.ifindex))
480
goto nla_put_failure;
481
482
nla_nest_end(skb, tb);
483
484
tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INFO);
485
486
if (!tb)
487
goto nla_info_failure;
488
489
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE,
490
mep->instance))
491
goto nla_put_failure;
492
493
if (nla_put(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC,
494
sizeof(mep->config.unicast_mac.addr),
495
mep->config.unicast_mac.addr))
496
goto nla_put_failure;
497
498
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL,
499
mep->config.mdlevel))
500
goto nla_put_failure;
501
502
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID,
503
mep->config.mepid))
504
goto nla_put_failure;
505
506
nla_nest_end(skb, tb);
507
508
tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INFO);
509
510
if (!tb)
511
goto nla_info_failure;
512
513
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE,
514
mep->instance))
515
goto nla_put_failure;
516
517
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE,
518
mep->cc_config.enable))
519
goto nla_put_failure;
520
521
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL,
522
mep->cc_config.exp_interval))
523
goto nla_put_failure;
524
525
if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID,
526
sizeof(mep->cc_config.exp_maid.data),
527
mep->cc_config.exp_maid.data))
528
goto nla_put_failure;
529
530
nla_nest_end(skb, tb);
531
532
tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_RDI_INFO);
533
534
if (!tb)
535
goto nla_info_failure;
536
537
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_INSTANCE,
538
mep->instance))
539
goto nla_put_failure;
540
541
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_RDI,
542
mep->rdi))
543
goto nla_put_failure;
544
545
nla_nest_end(skb, tb);
546
547
tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INFO);
548
549
if (!tb)
550
goto nla_info_failure;
551
552
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE,
553
mep->instance))
554
goto nla_put_failure;
555
556
if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC,
557
sizeof(mep->cc_ccm_tx_info.dmac),
558
mep->cc_ccm_tx_info.dmac.addr))
559
goto nla_put_failure;
560
561
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE,
562
mep->cc_ccm_tx_info.seq_no_update))
563
goto nla_put_failure;
564
565
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD,
566
mep->cc_ccm_tx_info.period))
567
goto nla_put_failure;
568
569
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV,
570
mep->cc_ccm_tx_info.if_tlv))
571
goto nla_put_failure;
572
573
if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE,
574
mep->cc_ccm_tx_info.if_tlv_value))
575
goto nla_put_failure;
576
577
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV,
578
mep->cc_ccm_tx_info.port_tlv))
579
goto nla_put_failure;
580
581
if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE,
582
mep->cc_ccm_tx_info.port_tlv_value))
583
goto nla_put_failure;
584
585
nla_nest_end(skb, tb);
586
587
hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) {
588
tb = nla_nest_start(skb,
589
IFLA_BRIDGE_CFM_CC_PEER_MEP_INFO);
590
591
if (!tb)
592
goto nla_info_failure;
593
594
if (nla_put_u32(skb,
595
IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE,
596
mep->instance))
597
goto nla_put_failure;
598
599
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_MEPID,
600
peer_mep->mepid))
601
goto nla_put_failure;
602
603
nla_nest_end(skb, tb);
604
}
605
}
606
607
return 0;
608
609
nla_put_failure:
610
nla_nest_cancel(skb, tb);
611
612
nla_info_failure:
613
return -EMSGSIZE;
614
}
615
616
int br_cfm_status_fill_info(struct sk_buff *skb,
617
struct net_bridge *br,
618
bool getlink)
619
{
620
struct br_cfm_peer_mep *peer_mep;
621
struct br_cfm_mep *mep;
622
struct nlattr *tb;
623
624
hlist_for_each_entry_rcu(mep, &br->mep_list, head) {
625
tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INFO);
626
if (!tb)
627
goto nla_info_failure;
628
629
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE,
630
mep->instance))
631
goto nla_put_failure;
632
633
if (nla_put_u32(skb,
634
IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN,
635
mep->status.opcode_unexp_seen))
636
goto nla_put_failure;
637
638
if (nla_put_u32(skb,
639
IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN,
640
mep->status.version_unexp_seen))
641
goto nla_put_failure;
642
643
if (nla_put_u32(skb,
644
IFLA_BRIDGE_CFM_MEP_STATUS_RX_LEVEL_LOW_SEEN,
645
mep->status.rx_level_low_seen))
646
goto nla_put_failure;
647
648
/* Only clear if this is a GETLINK */
649
if (getlink) {
650
/* Clear all 'seen' indications */
651
mep->status.opcode_unexp_seen = false;
652
mep->status.version_unexp_seen = false;
653
mep->status.rx_level_low_seen = false;
654
}
655
656
nla_nest_end(skb, tb);
657
658
hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) {
659
tb = nla_nest_start(skb,
660
IFLA_BRIDGE_CFM_CC_PEER_STATUS_INFO);
661
if (!tb)
662
goto nla_info_failure;
663
664
if (nla_put_u32(skb,
665
IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE,
666
mep->instance))
667
goto nla_put_failure;
668
669
if (nla_put_u32(skb,
670
IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID,
671
peer_mep->mepid))
672
goto nla_put_failure;
673
674
if (nla_put_u32(skb,
675
IFLA_BRIDGE_CFM_CC_PEER_STATUS_CCM_DEFECT,
676
peer_mep->cc_status.ccm_defect))
677
goto nla_put_failure;
678
679
if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI,
680
peer_mep->cc_status.rdi))
681
goto nla_put_failure;
682
683
if (nla_put_u8(skb,
684
IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE,
685
peer_mep->cc_status.port_tlv_value))
686
goto nla_put_failure;
687
688
if (nla_put_u8(skb,
689
IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE,
690
peer_mep->cc_status.if_tlv_value))
691
goto nla_put_failure;
692
693
if (nla_put_u32(skb,
694
IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN,
695
peer_mep->cc_status.seen))
696
goto nla_put_failure;
697
698
if (nla_put_u32(skb,
699
IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN,
700
peer_mep->cc_status.tlv_seen))
701
goto nla_put_failure;
702
703
if (nla_put_u32(skb,
704
IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEQ_UNEXP_SEEN,
705
peer_mep->cc_status.seq_unexp_seen))
706
goto nla_put_failure;
707
708
if (getlink) { /* Only clear if this is a GETLINK */
709
/* Clear all 'seen' indications */
710
peer_mep->cc_status.seen = false;
711
peer_mep->cc_status.tlv_seen = false;
712
peer_mep->cc_status.seq_unexp_seen = false;
713
}
714
715
nla_nest_end(skb, tb);
716
}
717
}
718
719
return 0;
720
721
nla_put_failure:
722
nla_nest_cancel(skb, tb);
723
724
nla_info_failure:
725
return -EMSGSIZE;
726
}
727
728