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
;
98 err
= nla_parse_nested(tb
, IFLA_BRIDGE_CFM_MEP_CREATE_MAX
, attr
,
99 br_cfm_mep_create_policy
, extack
);
103 if (!tb
[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE
]) {
104 NL_SET_ERR_MSG_MOD(extack
, "Missing INSTANCE attribute");
107 if (!tb
[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN
]) {
108 NL_SET_ERR_MSG_MOD(extack
, "Missing DOMAIN attribute");
111 if (!tb
[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION
]) {
112 NL_SET_ERR_MSG_MOD(extack
, "Missing DIRECTION attribute");
115 if (!tb
[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX
]) {
116 NL_SET_ERR_MSG_MOD(extack
, "Missing IFINDEX attribute");
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];
137 err
= nla_parse_nested(tb
, IFLA_BRIDGE_CFM_MEP_DELETE_MAX
, attr
,
138 br_cfm_mep_delete_policy
, extack
);
142 if (!tb
[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE
]) {
143 NL_SET_ERR_MSG_MOD(extack
,
144 "Missing INSTANCE attribute");
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
;
161 err
= nla_parse_nested(tb
, IFLA_BRIDGE_CFM_MEP_CONFIG_MAX
, attr
,
162 br_cfm_mep_config_policy
, extack
);
166 if (!tb
[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE
]) {
167 NL_SET_ERR_MSG_MOD(extack
, "Missing INSTANCE attribute");
170 if (!tb
[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC
]) {
171 NL_SET_ERR_MSG_MOD(extack
, "Missing UNICAST_MAC attribute");
174 if (!tb
[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL
]) {
175 NL_SET_ERR_MSG_MOD(extack
, "Missing MDLEVEL attribute");
178 if (!tb
[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID
]) {
179 NL_SET_ERR_MSG_MOD(extack
, "Missing MEPID attribute");
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
;
203 err
= nla_parse_nested(tb
, IFLA_BRIDGE_CFM_CC_CONFIG_MAX
, attr
,
204 br_cfm_cc_config_policy
, extack
);
208 if (!tb
[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE
]) {
209 NL_SET_ERR_MSG_MOD(extack
, "Missing INSTANCE attribute");
212 if (!tb
[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE
]) {
213 NL_SET_ERR_MSG_MOD(extack
, "Missing ENABLE attribute");
216 if (!tb
[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL
]) {
217 NL_SET_ERR_MSG_MOD(extack
, "Missing INTERVAL attribute");
220 if (!tb
[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID
]) {
221 NL_SET_ERR_MSG_MOD(extack
, "Missing MAID attribute");
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
;
243 err
= nla_parse_nested(tb
, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX
, attr
,
244 br_cfm_cc_peer_mep_policy
, extack
);
248 if (!tb
[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE
]) {
249 NL_SET_ERR_MSG_MOD(extack
, "Missing INSTANCE attribute");
252 if (!tb
[IFLA_BRIDGE_CFM_CC_PEER_MEPID
]) {
253 NL_SET_ERR_MSG_MOD(extack
, "Missing PEER_MEP_ID attribute");
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
;
270 err
= nla_parse_nested(tb
, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX
, attr
,
271 br_cfm_cc_peer_mep_policy
, extack
);
275 if (!tb
[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE
]) {
276 NL_SET_ERR_MSG_MOD(extack
, "Missing INSTANCE attribute");
279 if (!tb
[IFLA_BRIDGE_CFM_CC_PEER_MEPID
]) {
280 NL_SET_ERR_MSG_MOD(extack
, "Missing PEER_MEP_ID attribute");
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];
297 err
= nla_parse_nested(tb
, IFLA_BRIDGE_CFM_CC_RDI_MAX
, attr
,
298 br_cfm_cc_rdi_policy
, extack
);
302 if (!tb
[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE
]) {
303 NL_SET_ERR_MSG_MOD(extack
, "Missing INSTANCE attribute");
306 if (!tb
[IFLA_BRIDGE_CFM_CC_RDI_RDI
]) {
307 NL_SET_ERR_MSG_MOD(extack
, "Missing RDI attribute");
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
;
325 err
= nla_parse_nested(tb
, IFLA_BRIDGE_CFM_CC_CCM_TX_MAX
, attr
,
326 br_cfm_cc_ccm_tx_policy
, extack
);
330 if (!tb
[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE
]) {
331 NL_SET_ERR_MSG_MOD(extack
, "Missing INSTANCE attribute");
334 if (!tb
[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC
]) {
335 NL_SET_ERR_MSG_MOD(extack
, "Missing DMAC attribute");
338 if (!tb
[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE
]) {
339 NL_SET_ERR_MSG_MOD(extack
, "Missing SEQ_NO_UPDATE attribute");
342 if (!tb
[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD
]) {
343 NL_SET_ERR_MSG_MOD(extack
, "Missing PERIOD attribute");
346 if (!tb
[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV
]) {
347 NL_SET_ERR_MSG_MOD(extack
, "Missing IF_TLV attribute");
350 if (!tb
[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE
]) {
351 NL_SET_ERR_MSG_MOD(extack
, "Missing IF_TLV_VALUE attribute");
354 if (!tb
[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV
]) {
355 NL_SET_ERR_MSG_MOD(extack
, "Missing PORT_TLV attribute");
358 if (!tb
[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE
]) {
359 NL_SET_ERR_MSG_MOD(extack
, "Missing PORT_TLV_VALUE attribute");
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];
385 /* When this function is called for a port then the br pointer is
386 * invalid, therefor set the br to point correctly
391 err
= nla_parse_nested(tb
, IFLA_BRIDGE_CFM_MAX
, attr
,
392 br_cfm_policy
, extack
);
396 if (tb
[IFLA_BRIDGE_CFM_MEP_CREATE
]) {
397 err
= br_mep_create_parse(br
, tb
[IFLA_BRIDGE_CFM_MEP_CREATE
],
403 if (tb
[IFLA_BRIDGE_CFM_MEP_DELETE
]) {
404 err
= br_mep_delete_parse(br
, tb
[IFLA_BRIDGE_CFM_MEP_DELETE
],
410 if (tb
[IFLA_BRIDGE_CFM_MEP_CONFIG
]) {
411 err
= br_mep_config_parse(br
, tb
[IFLA_BRIDGE_CFM_MEP_CONFIG
],
417 if (tb
[IFLA_BRIDGE_CFM_CC_CONFIG
]) {
418 err
= br_cc_config_parse(br
, tb
[IFLA_BRIDGE_CFM_CC_CONFIG
],
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
],
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
],
438 if (tb
[IFLA_BRIDGE_CFM_CC_RDI
]) {
439 err
= br_cc_rdi_parse(br
, tb
[IFLA_BRIDGE_CFM_CC_RDI
],
445 if (tb
[IFLA_BRIDGE_CFM_CC_CCM_TX
]) {
446 err
= br_cc_ccm_tx_parse(br
, tb
[IFLA_BRIDGE_CFM_CC_CCM_TX
],
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
;
461 hlist_for_each_entry_rcu(mep
, &br
->mep_list
, head
) {
462 tb
= nla_nest_start(skb
, IFLA_BRIDGE_CFM_MEP_CREATE_INFO
);
464 goto nla_info_failure
;
466 if (nla_put_u32(skb
, IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE
,
468 goto nla_put_failure
;
470 if (nla_put_u32(skb
, IFLA_BRIDGE_CFM_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
);
487 goto nla_info_failure
;
489 if (nla_put_u32(skb
, IFLA_BRIDGE_CFM_MEP_CONFIG_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
,
504 goto nla_put_failure
;
506 nla_nest_end(skb
, tb
);
508 tb
= nla_nest_start(skb
, IFLA_BRIDGE_CFM_CC_CONFIG_INFO
);
511 goto nla_info_failure
;
513 if (nla_put_u32(skb
, IFLA_BRIDGE_CFM_CC_CONFIG_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
);
535 goto nla_info_failure
;
537 if (nla_put_u32(skb
, IFLA_BRIDGE_CFM_CC_RDI_INSTANCE
,
539 goto nla_put_failure
;
541 if (nla_put_u32(skb
, IFLA_BRIDGE_CFM_CC_RDI_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
);
550 goto nla_info_failure
;
552 if (nla_put_u32(skb
, IFLA_BRIDGE_CFM_CC_CCM_TX_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
);
592 goto nla_info_failure
;
595 IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE
,
597 goto nla_put_failure
;
599 if (nla_put_u32(skb
, IFLA_BRIDGE_CFM_CC_PEER_MEPID
,
601 goto nla_put_failure
;
603 nla_nest_end(skb
, tb
);
610 nla_nest_cancel(skb
, tb
);
616 int br_cfm_status_fill_info(struct sk_buff
*skb
,
617 struct net_bridge
*br
,
620 struct br_cfm_peer_mep
*peer_mep
;
621 struct br_cfm_mep
*mep
;
624 hlist_for_each_entry_rcu(mep
, &br
->mep_list
, head
) {
625 tb
= nla_nest_start(skb
, IFLA_BRIDGE_CFM_MEP_STATUS_INFO
);
627 goto nla_info_failure
;
629 if (nla_put_u32(skb
, IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE
,
631 goto nla_put_failure
;
634 IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN
,
635 mep
->status
.opcode_unexp_seen
))
636 goto nla_put_failure
;
639 IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN
,
640 mep
->status
.version_unexp_seen
))
641 goto nla_put_failure
;
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 */
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
);
662 goto nla_info_failure
;
665 IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE
,
667 goto nla_put_failure
;
670 IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID
,
672 goto nla_put_failure
;
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
;
684 IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE
,
685 peer_mep
->cc_status
.port_tlv_value
))
686 goto nla_put_failure
;
689 IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE
,
690 peer_mep
->cc_status
.if_tlv_value
))
691 goto nla_put_failure
;
694 IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN
,
695 peer_mep
->cc_status
.seen
))
696 goto nla_put_failure
;
699 IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN
,
700 peer_mep
->cc_status
.tlv_seen
))
701 goto nla_put_failure
;
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
);
722 nla_nest_cancel(skb
, tb
);