WIP FPC-III support
[linux/fpc-iii.git] / net / bridge / br_cfm_netlink.c
blob5c4c369f8536e931a86201dfbfc07f452d8e187f
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 #include <net/genetlink.h>
5 #include "br_private.h"
6 #include "br_private_cfm.h"
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 },
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 },
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),
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 },
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),
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 },
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 },
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),
90 static int br_mep_create_parse(struct net_bridge *br, struct nlattr *attr,
91 struct netlink_ext_ack *extack)
93 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1];
94 struct br_cfm_mep_create create;
95 u32 instance;
96 int err;
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;
103 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]) {
104 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
105 return -EINVAL;
107 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]) {
108 NL_SET_ERR_MSG_MOD(extack, "Missing DOMAIN attribute");
109 return -EINVAL;
111 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]) {
112 NL_SET_ERR_MSG_MOD(extack, "Missing DIRECTION attribute");
113 return -EINVAL;
115 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]) {
116 NL_SET_ERR_MSG_MOD(extack, "Missing IFINDEX attribute");
117 return -EINVAL;
120 memset(&create, 0, sizeof(create));
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]);
127 return br_cfm_mep_create(br, instance, &create, extack);
130 static int br_mep_delete_parse(struct net_bridge *br, struct nlattr *attr,
131 struct netlink_ext_ack *extack)
133 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1];
134 u32 instance;
135 int err;
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;
142 if (!tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]) {
143 NL_SET_ERR_MSG_MOD(extack,
144 "Missing INSTANCE attribute");
145 return -EINVAL;
148 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]);
150 return br_cfm_mep_delete(br, instance, extack);
153 static int br_mep_config_parse(struct net_bridge *br, struct nlattr *attr,
154 struct netlink_ext_ack *extack)
156 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1];
157 struct br_cfm_mep_config config;
158 u32 instance;
159 int err;
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;
166 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]) {
167 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
168 return -EINVAL;
170 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC]) {
171 NL_SET_ERR_MSG_MOD(extack, "Missing UNICAST_MAC attribute");
172 return -EINVAL;
174 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]) {
175 NL_SET_ERR_MSG_MOD(extack, "Missing MDLEVEL attribute");
176 return -EINVAL;
178 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]) {
179 NL_SET_ERR_MSG_MOD(extack, "Missing MEPID attribute");
180 return -EINVAL;
183 memset(&config, 0, sizeof(config));
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]);
192 return br_cfm_mep_config_set(br, instance, &config, extack);
195 static int br_cc_config_parse(struct net_bridge *br, struct nlattr *attr,
196 struct netlink_ext_ack *extack)
198 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1];
199 struct br_cfm_cc_config config;
200 u32 instance;
201 int err;
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;
208 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]) {
209 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
210 return -EINVAL;
212 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]) {
213 NL_SET_ERR_MSG_MOD(extack, "Missing ENABLE attribute");
214 return -EINVAL;
216 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]) {
217 NL_SET_ERR_MSG_MOD(extack, "Missing INTERVAL attribute");
218 return -EINVAL;
220 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]) {
221 NL_SET_ERR_MSG_MOD(extack, "Missing MAID attribute");
222 return -EINVAL;
225 memset(&config, 0, sizeof(config));
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));
233 return br_cfm_cc_config_set(br, instance, &config, extack);
236 static int br_cc_peer_mep_add_parse(struct net_bridge *br, struct nlattr *attr,
237 struct netlink_ext_ack *extack)
239 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
240 u32 instance, peer_mep_id;
241 int err;
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;
248 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
249 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
250 return -EINVAL;
252 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
253 NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
254 return -EINVAL;
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]);
260 return br_cfm_cc_peer_mep_add(br, instance, peer_mep_id, extack);
263 static int br_cc_peer_mep_remove_parse(struct net_bridge *br, struct nlattr *attr,
264 struct netlink_ext_ack *extack)
266 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
267 u32 instance, peer_mep_id;
268 int err;
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;
275 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
276 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
277 return -EINVAL;
279 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
280 NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
281 return -EINVAL;
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]);
287 return br_cfm_cc_peer_mep_remove(br, instance, peer_mep_id, extack);
290 static int br_cc_rdi_parse(struct net_bridge *br, struct nlattr *attr,
291 struct netlink_ext_ack *extack)
293 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1];
294 u32 instance, rdi;
295 int err;
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;
302 if (!tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]) {
303 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
304 return -EINVAL;
306 if (!tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]) {
307 NL_SET_ERR_MSG_MOD(extack, "Missing RDI attribute");
308 return -EINVAL;
311 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]);
312 rdi = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]);
314 return br_cfm_cc_rdi_set(br, instance, rdi, extack);
317 static int br_cc_ccm_tx_parse(struct net_bridge *br, struct nlattr *attr,
318 struct netlink_ext_ack *extack)
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;
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;
330 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]) {
331 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
332 return -EINVAL;
334 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]) {
335 NL_SET_ERR_MSG_MOD(extack, "Missing DMAC attribute");
336 return -EINVAL;
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;
342 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]) {
343 NL_SET_ERR_MSG_MOD(extack, "Missing PERIOD attribute");
344 return -EINVAL;
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;
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;
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;
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;
363 memset(&tx_info, 0, sizeof(tx_info));
365 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_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]);
376 return br_cfm_cc_ccm_tx(br, instance, &tx_info, extack);
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)
382 struct nlattr *tb[IFLA_BRIDGE_CFM_MAX + 1];
383 int err;
385 /* When this function is called for a port then the br pointer is
386 * invalid, therefor set the br to point correctly
388 if (p)
389 br = p->br;
391 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MAX, attr,
392 br_cfm_policy, extack);
393 if (err)
394 return err;
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;
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;
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;
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;
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;
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;
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;
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;
452 return 0;
455 int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br)
457 struct br_cfm_peer_mep *peer_mep;
458 struct br_cfm_mep *mep;
459 struct nlattr *tb;
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;
466 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE,
467 mep->instance))
468 goto nla_put_failure;
470 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN,
471 mep->create.domain))
472 goto nla_put_failure;
474 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION,
475 mep->create.direction))
476 goto nla_put_failure;
478 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX,
479 mep->create.ifindex))
480 goto nla_put_failure;
482 nla_nest_end(skb, tb);
484 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INFO);
486 if (!tb)
487 goto nla_info_failure;
489 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE,
490 mep->instance))
491 goto nla_put_failure;
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;
498 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL,
499 mep->config.mdlevel))
500 goto nla_put_failure;
502 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID,
503 mep->config.mepid))
504 goto nla_put_failure;
506 nla_nest_end(skb, tb);
508 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INFO);
510 if (!tb)
511 goto nla_info_failure;
513 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE,
514 mep->instance))
515 goto nla_put_failure;
517 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE,
518 mep->cc_config.enable))
519 goto nla_put_failure;
521 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL,
522 mep->cc_config.exp_interval))
523 goto nla_put_failure;
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;
530 nla_nest_end(skb, tb);
532 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_RDI_INFO);
534 if (!tb)
535 goto nla_info_failure;
537 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_INSTANCE,
538 mep->instance))
539 goto nla_put_failure;
541 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_RDI,
542 mep->rdi))
543 goto nla_put_failure;
545 nla_nest_end(skb, tb);
547 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INFO);
549 if (!tb)
550 goto nla_info_failure;
552 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE,
553 mep->instance))
554 goto nla_put_failure;
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;
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;
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;
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;
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;
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;
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;
585 nla_nest_end(skb, tb);
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);
591 if (!tb)
592 goto nla_info_failure;
594 if (nla_put_u32(skb,
595 IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE,
596 mep->instance))
597 goto nla_put_failure;
599 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_MEPID,
600 peer_mep->mepid))
601 goto nla_put_failure;
603 nla_nest_end(skb, tb);
607 return 0;
609 nla_put_failure:
610 nla_nest_cancel(skb, tb);
612 nla_info_failure:
613 return -EMSGSIZE;
616 int br_cfm_status_fill_info(struct sk_buff *skb,
617 struct net_bridge *br,
618 bool getlink)
620 struct br_cfm_peer_mep *peer_mep;
621 struct br_cfm_mep *mep;
622 struct nlattr *tb;
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;
629 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE,
630 mep->instance))
631 goto nla_put_failure;
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;
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;
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;
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;
656 nla_nest_end(skb, tb);
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;
664 if (nla_put_u32(skb,
665 IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE,
666 mep->instance))
667 goto nla_put_failure;
669 if (nla_put_u32(skb,
670 IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID,
671 peer_mep->mepid))
672 goto nla_put_failure;
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;
679 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI,
680 peer_mep->cc_status.rdi))
681 goto nla_put_failure;
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;
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;
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;
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;
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;
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;
715 nla_nest_end(skb, tb);
719 return 0;
721 nla_put_failure:
722 nla_nest_cancel(skb, tb);
724 nla_info_failure:
725 return -EMSGSIZE;