162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <net/genetlink.h>
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include "br_private.h"
662306a36Sopenharmony_ci#include "br_private_cfm.h"
762306a36Sopenharmony_ci
862306a36Sopenharmony_cistatic const struct nla_policy
962306a36Sopenharmony_cibr_cfm_mep_create_policy[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1] = {
1062306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CREATE_UNSPEC]	= { .type = NLA_REJECT },
1162306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]	= { .type = NLA_U32 },
1262306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]	= { .type = NLA_U32 },
1362306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]	= { .type = NLA_U32 },
1462306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]	= { .type = NLA_U32 },
1562306a36Sopenharmony_ci};
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic const struct nla_policy
1862306a36Sopenharmony_cibr_cfm_mep_delete_policy[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1] = {
1962306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_DELETE_UNSPEC]	= { .type = NLA_REJECT },
2062306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]	= { .type = NLA_U32 },
2162306a36Sopenharmony_ci};
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic const struct nla_policy
2462306a36Sopenharmony_cibr_cfm_mep_config_policy[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1] = {
2562306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CONFIG_UNSPEC]	 = { .type = NLA_REJECT },
2662306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]	 = { .type = NLA_U32 },
2762306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC] = NLA_POLICY_ETH_ADDR,
2862306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]	 = NLA_POLICY_MAX(NLA_U32, 7),
2962306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]	 = NLA_POLICY_MAX(NLA_U32, 0x1FFF),
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic const struct nla_policy
3362306a36Sopenharmony_cibr_cfm_cc_config_policy[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1] = {
3462306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC]	 = { .type = NLA_REJECT },
3562306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]	 = { .type = NLA_U32 },
3662306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]	 = { .type = NLA_U32 },
3762306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = { .type = NLA_U32 },
3862306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]	 = {
3962306a36Sopenharmony_ci	.type = NLA_BINARY, .len = CFM_MAID_LENGTH },
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic const struct nla_policy
4362306a36Sopenharmony_cibr_cfm_cc_peer_mep_policy[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1] = {
4462306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_PEER_MEP_UNSPEC]	= { .type = NLA_REJECT },
4562306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]	= { .type = NLA_U32 },
4662306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_PEER_MEPID]		= NLA_POLICY_MAX(NLA_U32, 0x1FFF),
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic const struct nla_policy
5062306a36Sopenharmony_cibr_cfm_cc_rdi_policy[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1] = {
5162306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_RDI_UNSPEC]		= { .type = NLA_REJECT },
5262306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]	= { .type = NLA_U32 },
5362306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_RDI_RDI]		= { .type = NLA_U32 },
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic const struct nla_policy
5762306a36Sopenharmony_cibr_cfm_cc_ccm_tx_policy[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1] = {
5862306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CCM_TX_UNSPEC]	   = { .type = NLA_REJECT },
5962306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]	   = { .type = NLA_U32 },
6062306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]	   = NLA_POLICY_ETH_ADDR,
6162306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]  = { .type = NLA_U32 },
6262306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]	   = { .type = NLA_U32 },
6362306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]	   = { .type = NLA_U32 },
6462306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]   = { .type = NLA_U8 },
6562306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]	   = { .type = NLA_U32 },
6662306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE] = { .type = NLA_U8 },
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic const struct nla_policy
7062306a36Sopenharmony_cibr_cfm_policy[IFLA_BRIDGE_CFM_MAX + 1] = {
7162306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_UNSPEC]		= { .type = NLA_REJECT },
7262306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CREATE]		=
7362306a36Sopenharmony_ci				NLA_POLICY_NESTED(br_cfm_mep_create_policy),
7462306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_DELETE]		=
7562306a36Sopenharmony_ci				NLA_POLICY_NESTED(br_cfm_mep_delete_policy),
7662306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_MEP_CONFIG]		=
7762306a36Sopenharmony_ci				NLA_POLICY_NESTED(br_cfm_mep_config_policy),
7862306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CONFIG]		=
7962306a36Sopenharmony_ci				NLA_POLICY_NESTED(br_cfm_cc_config_policy),
8062306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]	=
8162306a36Sopenharmony_ci				NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy),
8262306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]	=
8362306a36Sopenharmony_ci				NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy),
8462306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_RDI]		=
8562306a36Sopenharmony_ci				NLA_POLICY_NESTED(br_cfm_cc_rdi_policy),
8662306a36Sopenharmony_ci	[IFLA_BRIDGE_CFM_CC_CCM_TX]		=
8762306a36Sopenharmony_ci				NLA_POLICY_NESTED(br_cfm_cc_ccm_tx_policy),
8862306a36Sopenharmony_ci};
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic int br_mep_create_parse(struct net_bridge *br, struct nlattr *attr,
9162306a36Sopenharmony_ci			       struct netlink_ext_ack *extack)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1];
9462306a36Sopenharmony_ci	struct br_cfm_mep_create create;
9562306a36Sopenharmony_ci	u32 instance;
9662306a36Sopenharmony_ci	int err;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CREATE_MAX, attr,
9962306a36Sopenharmony_ci			       br_cfm_mep_create_policy, extack);
10062306a36Sopenharmony_ci	if (err)
10162306a36Sopenharmony_ci		return err;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]) {
10462306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
10562306a36Sopenharmony_ci		return -EINVAL;
10662306a36Sopenharmony_ci	}
10762306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]) {
10862306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing DOMAIN attribute");
10962306a36Sopenharmony_ci		return -EINVAL;
11062306a36Sopenharmony_ci	}
11162306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]) {
11262306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing DIRECTION attribute");
11362306a36Sopenharmony_ci		return -EINVAL;
11462306a36Sopenharmony_ci	}
11562306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]) {
11662306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing IFINDEX attribute");
11762306a36Sopenharmony_ci		return -EINVAL;
11862306a36Sopenharmony_ci	}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	memset(&create, 0, sizeof(create));
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]);
12362306a36Sopenharmony_ci	create.domain = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]);
12462306a36Sopenharmony_ci	create.direction = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]);
12562306a36Sopenharmony_ci	create.ifindex = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return br_cfm_mep_create(br, instance, &create, extack);
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic int br_mep_delete_parse(struct net_bridge *br, struct nlattr *attr,
13162306a36Sopenharmony_ci			       struct netlink_ext_ack *extack)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1];
13462306a36Sopenharmony_ci	u32 instance;
13562306a36Sopenharmony_ci	int err;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_DELETE_MAX, attr,
13862306a36Sopenharmony_ci			       br_cfm_mep_delete_policy, extack);
13962306a36Sopenharmony_ci	if (err)
14062306a36Sopenharmony_ci		return err;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]) {
14362306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack,
14462306a36Sopenharmony_ci				   "Missing INSTANCE attribute");
14562306a36Sopenharmony_ci		return -EINVAL;
14662306a36Sopenharmony_ci	}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	return br_cfm_mep_delete(br, instance, extack);
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic int br_mep_config_parse(struct net_bridge *br, struct nlattr *attr,
15462306a36Sopenharmony_ci			       struct netlink_ext_ack *extack)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1];
15762306a36Sopenharmony_ci	struct br_cfm_mep_config config;
15862306a36Sopenharmony_ci	u32 instance;
15962306a36Sopenharmony_ci	int err;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CONFIG_MAX, attr,
16262306a36Sopenharmony_ci			       br_cfm_mep_config_policy, extack);
16362306a36Sopenharmony_ci	if (err)
16462306a36Sopenharmony_ci		return err;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]) {
16762306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
16862306a36Sopenharmony_ci		return -EINVAL;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC]) {
17162306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing UNICAST_MAC attribute");
17262306a36Sopenharmony_ci		return -EINVAL;
17362306a36Sopenharmony_ci	}
17462306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]) {
17562306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing MDLEVEL attribute");
17662306a36Sopenharmony_ci		return -EINVAL;
17762306a36Sopenharmony_ci	}
17862306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]) {
17962306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing MEPID attribute");
18062306a36Sopenharmony_ci		return -EINVAL;
18162306a36Sopenharmony_ci	}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	memset(&config, 0, sizeof(config));
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]);
18662306a36Sopenharmony_ci	nla_memcpy(&config.unicast_mac.addr,
18762306a36Sopenharmony_ci		   tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC],
18862306a36Sopenharmony_ci		   sizeof(config.unicast_mac.addr));
18962306a36Sopenharmony_ci	config.mdlevel = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]);
19062306a36Sopenharmony_ci	config.mepid = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	return br_cfm_mep_config_set(br, instance, &config, extack);
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistatic int br_cc_config_parse(struct net_bridge *br, struct nlattr *attr,
19662306a36Sopenharmony_ci			      struct netlink_ext_ack *extack)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1];
19962306a36Sopenharmony_ci	struct br_cfm_cc_config config;
20062306a36Sopenharmony_ci	u32 instance;
20162306a36Sopenharmony_ci	int err;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CONFIG_MAX, attr,
20462306a36Sopenharmony_ci			       br_cfm_cc_config_policy, extack);
20562306a36Sopenharmony_ci	if (err)
20662306a36Sopenharmony_ci		return err;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]) {
20962306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
21062306a36Sopenharmony_ci		return -EINVAL;
21162306a36Sopenharmony_ci	}
21262306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]) {
21362306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing ENABLE attribute");
21462306a36Sopenharmony_ci		return -EINVAL;
21562306a36Sopenharmony_ci	}
21662306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]) {
21762306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing INTERVAL attribute");
21862306a36Sopenharmony_ci		return -EINVAL;
21962306a36Sopenharmony_ci	}
22062306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]) {
22162306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing MAID attribute");
22262306a36Sopenharmony_ci		return -EINVAL;
22362306a36Sopenharmony_ci	}
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	memset(&config, 0, sizeof(config));
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]);
22862306a36Sopenharmony_ci	config.enable = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]);
22962306a36Sopenharmony_ci	config.exp_interval = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]);
23062306a36Sopenharmony_ci	nla_memcpy(&config.exp_maid.data, tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID],
23162306a36Sopenharmony_ci		   sizeof(config.exp_maid.data));
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	return br_cfm_cc_config_set(br, instance, &config, extack);
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic int br_cc_peer_mep_add_parse(struct net_bridge *br, struct nlattr *attr,
23762306a36Sopenharmony_ci				    struct netlink_ext_ack *extack)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
24062306a36Sopenharmony_ci	u32 instance, peer_mep_id;
24162306a36Sopenharmony_ci	int err;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr,
24462306a36Sopenharmony_ci			       br_cfm_cc_peer_mep_policy, extack);
24562306a36Sopenharmony_ci	if (err)
24662306a36Sopenharmony_ci		return err;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
24962306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
25062306a36Sopenharmony_ci		return -EINVAL;
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
25362306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
25462306a36Sopenharmony_ci		return -EINVAL;
25562306a36Sopenharmony_ci	}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]);
25862306a36Sopenharmony_ci	peer_mep_id =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]);
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	return br_cfm_cc_peer_mep_add(br, instance, peer_mep_id, extack);
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_cistatic int br_cc_peer_mep_remove_parse(struct net_bridge *br, struct nlattr *attr,
26462306a36Sopenharmony_ci				       struct netlink_ext_ack *extack)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
26762306a36Sopenharmony_ci	u32 instance, peer_mep_id;
26862306a36Sopenharmony_ci	int err;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr,
27162306a36Sopenharmony_ci			       br_cfm_cc_peer_mep_policy, extack);
27262306a36Sopenharmony_ci	if (err)
27362306a36Sopenharmony_ci		return err;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
27662306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
27762306a36Sopenharmony_ci		return -EINVAL;
27862306a36Sopenharmony_ci	}
27962306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
28062306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
28162306a36Sopenharmony_ci		return -EINVAL;
28262306a36Sopenharmony_ci	}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]);
28562306a36Sopenharmony_ci	peer_mep_id =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	return br_cfm_cc_peer_mep_remove(br, instance, peer_mep_id, extack);
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistatic int br_cc_rdi_parse(struct net_bridge *br, struct nlattr *attr,
29162306a36Sopenharmony_ci			   struct netlink_ext_ack *extack)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1];
29462306a36Sopenharmony_ci	u32 instance, rdi;
29562306a36Sopenharmony_ci	int err;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_RDI_MAX, attr,
29862306a36Sopenharmony_ci			       br_cfm_cc_rdi_policy, extack);
29962306a36Sopenharmony_ci	if (err)
30062306a36Sopenharmony_ci		return err;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]) {
30362306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
30462306a36Sopenharmony_ci		return -EINVAL;
30562306a36Sopenharmony_ci	}
30662306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]) {
30762306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing RDI attribute");
30862306a36Sopenharmony_ci		return -EINVAL;
30962306a36Sopenharmony_ci	}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]);
31262306a36Sopenharmony_ci	rdi =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	return br_cfm_cc_rdi_set(br, instance, rdi, extack);
31562306a36Sopenharmony_ci}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic int br_cc_ccm_tx_parse(struct net_bridge *br, struct nlattr *attr,
31862306a36Sopenharmony_ci			      struct netlink_ext_ack *extack)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1];
32162306a36Sopenharmony_ci	struct br_cfm_cc_ccm_tx_info tx_info;
32262306a36Sopenharmony_ci	u32 instance;
32362306a36Sopenharmony_ci	int err;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CCM_TX_MAX, attr,
32662306a36Sopenharmony_ci			       br_cfm_cc_ccm_tx_policy, extack);
32762306a36Sopenharmony_ci	if (err)
32862306a36Sopenharmony_ci		return err;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]) {
33162306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
33262306a36Sopenharmony_ci		return -EINVAL;
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]) {
33562306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing DMAC attribute");
33662306a36Sopenharmony_ci		return -EINVAL;
33762306a36Sopenharmony_ci	}
33862306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]) {
33962306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing SEQ_NO_UPDATE attribute");
34062306a36Sopenharmony_ci		return -EINVAL;
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]) {
34362306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing PERIOD attribute");
34462306a36Sopenharmony_ci		return -EINVAL;
34562306a36Sopenharmony_ci	}
34662306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]) {
34762306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV attribute");
34862306a36Sopenharmony_ci		return -EINVAL;
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]) {
35162306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV_VALUE attribute");
35262306a36Sopenharmony_ci		return -EINVAL;
35362306a36Sopenharmony_ci	}
35462306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]) {
35562306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV attribute");
35662306a36Sopenharmony_ci		return -EINVAL;
35762306a36Sopenharmony_ci	}
35862306a36Sopenharmony_ci	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]) {
35962306a36Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV_VALUE attribute");
36062306a36Sopenharmony_ci		return -EINVAL;
36162306a36Sopenharmony_ci	}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	memset(&tx_info, 0, sizeof(tx_info));
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]);
36662306a36Sopenharmony_ci	nla_memcpy(&tx_info.dmac.addr,
36762306a36Sopenharmony_ci		   tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC],
36862306a36Sopenharmony_ci		   sizeof(tx_info.dmac.addr));
36962306a36Sopenharmony_ci	tx_info.seq_no_update = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]);
37062306a36Sopenharmony_ci	tx_info.period = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]);
37162306a36Sopenharmony_ci	tx_info.if_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]);
37262306a36Sopenharmony_ci	tx_info.if_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]);
37362306a36Sopenharmony_ci	tx_info.port_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]);
37462306a36Sopenharmony_ci	tx_info.port_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]);
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	return br_cfm_cc_ccm_tx(br, instance, &tx_info, extack);
37762306a36Sopenharmony_ci}
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ciint br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,
38062306a36Sopenharmony_ci		 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
38162306a36Sopenharmony_ci{
38262306a36Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_CFM_MAX + 1];
38362306a36Sopenharmony_ci	int err;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	/* When this function is called for a port then the br pointer is
38662306a36Sopenharmony_ci	 * invalid, therefor set the br to point correctly
38762306a36Sopenharmony_ci	 */
38862306a36Sopenharmony_ci	if (p)
38962306a36Sopenharmony_ci		br = p->br;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MAX, attr,
39262306a36Sopenharmony_ci			       br_cfm_policy, extack);
39362306a36Sopenharmony_ci	if (err)
39462306a36Sopenharmony_ci		return err;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	if (tb[IFLA_BRIDGE_CFM_MEP_CREATE]) {
39762306a36Sopenharmony_ci		err = br_mep_create_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CREATE],
39862306a36Sopenharmony_ci					  extack);
39962306a36Sopenharmony_ci		if (err)
40062306a36Sopenharmony_ci			return err;
40162306a36Sopenharmony_ci	}
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	if (tb[IFLA_BRIDGE_CFM_MEP_DELETE]) {
40462306a36Sopenharmony_ci		err = br_mep_delete_parse(br, tb[IFLA_BRIDGE_CFM_MEP_DELETE],
40562306a36Sopenharmony_ci					  extack);
40662306a36Sopenharmony_ci		if (err)
40762306a36Sopenharmony_ci			return err;
40862306a36Sopenharmony_ci	}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	if (tb[IFLA_BRIDGE_CFM_MEP_CONFIG]) {
41162306a36Sopenharmony_ci		err = br_mep_config_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CONFIG],
41262306a36Sopenharmony_ci					  extack);
41362306a36Sopenharmony_ci		if (err)
41462306a36Sopenharmony_ci			return err;
41562306a36Sopenharmony_ci	}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	if (tb[IFLA_BRIDGE_CFM_CC_CONFIG]) {
41862306a36Sopenharmony_ci		err = br_cc_config_parse(br, tb[IFLA_BRIDGE_CFM_CC_CONFIG],
41962306a36Sopenharmony_ci					 extack);
42062306a36Sopenharmony_ci		if (err)
42162306a36Sopenharmony_ci			return err;
42262306a36Sopenharmony_ci	}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]) {
42562306a36Sopenharmony_ci		err = br_cc_peer_mep_add_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD],
42662306a36Sopenharmony_ci					       extack);
42762306a36Sopenharmony_ci		if (err)
42862306a36Sopenharmony_ci			return err;
42962306a36Sopenharmony_ci	}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]) {
43262306a36Sopenharmony_ci		err = br_cc_peer_mep_remove_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE],
43362306a36Sopenharmony_ci						  extack);
43462306a36Sopenharmony_ci		if (err)
43562306a36Sopenharmony_ci			return err;
43662306a36Sopenharmony_ci	}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	if (tb[IFLA_BRIDGE_CFM_CC_RDI]) {
43962306a36Sopenharmony_ci		err = br_cc_rdi_parse(br, tb[IFLA_BRIDGE_CFM_CC_RDI],
44062306a36Sopenharmony_ci				      extack);
44162306a36Sopenharmony_ci		if (err)
44262306a36Sopenharmony_ci			return err;
44362306a36Sopenharmony_ci	}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	if (tb[IFLA_BRIDGE_CFM_CC_CCM_TX]) {
44662306a36Sopenharmony_ci		err = br_cc_ccm_tx_parse(br, tb[IFLA_BRIDGE_CFM_CC_CCM_TX],
44762306a36Sopenharmony_ci					 extack);
44862306a36Sopenharmony_ci		if (err)
44962306a36Sopenharmony_ci			return err;
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	return 0;
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ciint br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br)
45662306a36Sopenharmony_ci{
45762306a36Sopenharmony_ci	struct br_cfm_peer_mep *peer_mep;
45862306a36Sopenharmony_ci	struct br_cfm_mep *mep;
45962306a36Sopenharmony_ci	struct nlattr *tb;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	hlist_for_each_entry_rcu(mep, &br->mep_list, head) {
46262306a36Sopenharmony_ci		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INFO);
46362306a36Sopenharmony_ci		if (!tb)
46462306a36Sopenharmony_ci			goto nla_info_failure;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE,
46762306a36Sopenharmony_ci				mep->instance))
46862306a36Sopenharmony_ci			goto nla_put_failure;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN,
47162306a36Sopenharmony_ci				mep->create.domain))
47262306a36Sopenharmony_ci			goto nla_put_failure;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION,
47562306a36Sopenharmony_ci				mep->create.direction))
47662306a36Sopenharmony_ci			goto nla_put_failure;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX,
47962306a36Sopenharmony_ci				mep->create.ifindex))
48062306a36Sopenharmony_ci			goto nla_put_failure;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci		nla_nest_end(skb, tb);
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INFO);
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci		if (!tb)
48762306a36Sopenharmony_ci			goto nla_info_failure;
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE,
49062306a36Sopenharmony_ci				mep->instance))
49162306a36Sopenharmony_ci			goto nla_put_failure;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci		if (nla_put(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC,
49462306a36Sopenharmony_ci			    sizeof(mep->config.unicast_mac.addr),
49562306a36Sopenharmony_ci			    mep->config.unicast_mac.addr))
49662306a36Sopenharmony_ci			goto nla_put_failure;
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL,
49962306a36Sopenharmony_ci				mep->config.mdlevel))
50062306a36Sopenharmony_ci			goto nla_put_failure;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID,
50362306a36Sopenharmony_ci				mep->config.mepid))
50462306a36Sopenharmony_ci			goto nla_put_failure;
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci		nla_nest_end(skb, tb);
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INFO);
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci		if (!tb)
51162306a36Sopenharmony_ci			goto nla_info_failure;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE,
51462306a36Sopenharmony_ci				mep->instance))
51562306a36Sopenharmony_ci			goto nla_put_failure;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE,
51862306a36Sopenharmony_ci				mep->cc_config.enable))
51962306a36Sopenharmony_ci			goto nla_put_failure;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL,
52262306a36Sopenharmony_ci				mep->cc_config.exp_interval))
52362306a36Sopenharmony_ci			goto nla_put_failure;
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci		if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID,
52662306a36Sopenharmony_ci			    sizeof(mep->cc_config.exp_maid.data),
52762306a36Sopenharmony_ci			    mep->cc_config.exp_maid.data))
52862306a36Sopenharmony_ci			goto nla_put_failure;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci		nla_nest_end(skb, tb);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_RDI_INFO);
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci		if (!tb)
53562306a36Sopenharmony_ci			goto nla_info_failure;
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_INSTANCE,
53862306a36Sopenharmony_ci				mep->instance))
53962306a36Sopenharmony_ci			goto nla_put_failure;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_RDI,
54262306a36Sopenharmony_ci				mep->rdi))
54362306a36Sopenharmony_ci			goto nla_put_failure;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci		nla_nest_end(skb, tb);
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INFO);
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci		if (!tb)
55062306a36Sopenharmony_ci			goto nla_info_failure;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE,
55362306a36Sopenharmony_ci				mep->instance))
55462306a36Sopenharmony_ci			goto nla_put_failure;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci		if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC,
55762306a36Sopenharmony_ci			    sizeof(mep->cc_ccm_tx_info.dmac),
55862306a36Sopenharmony_ci			    mep->cc_ccm_tx_info.dmac.addr))
55962306a36Sopenharmony_ci			goto nla_put_failure;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE,
56262306a36Sopenharmony_ci				mep->cc_ccm_tx_info.seq_no_update))
56362306a36Sopenharmony_ci			goto nla_put_failure;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD,
56662306a36Sopenharmony_ci				mep->cc_ccm_tx_info.period))
56762306a36Sopenharmony_ci			goto nla_put_failure;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV,
57062306a36Sopenharmony_ci				mep->cc_ccm_tx_info.if_tlv))
57162306a36Sopenharmony_ci			goto nla_put_failure;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci		if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE,
57462306a36Sopenharmony_ci			       mep->cc_ccm_tx_info.if_tlv_value))
57562306a36Sopenharmony_ci			goto nla_put_failure;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV,
57862306a36Sopenharmony_ci				mep->cc_ccm_tx_info.port_tlv))
57962306a36Sopenharmony_ci			goto nla_put_failure;
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci		if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE,
58262306a36Sopenharmony_ci			       mep->cc_ccm_tx_info.port_tlv_value))
58362306a36Sopenharmony_ci			goto nla_put_failure;
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci		nla_nest_end(skb, tb);
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci		hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) {
58862306a36Sopenharmony_ci			tb = nla_nest_start(skb,
58962306a36Sopenharmony_ci					    IFLA_BRIDGE_CFM_CC_PEER_MEP_INFO);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci			if (!tb)
59262306a36Sopenharmony_ci				goto nla_info_failure;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci			if (nla_put_u32(skb,
59562306a36Sopenharmony_ci					IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE,
59662306a36Sopenharmony_ci					mep->instance))
59762306a36Sopenharmony_ci				goto nla_put_failure;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci			if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_MEPID,
60062306a36Sopenharmony_ci					peer_mep->mepid))
60162306a36Sopenharmony_ci				goto nla_put_failure;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci			nla_nest_end(skb, tb);
60462306a36Sopenharmony_ci		}
60562306a36Sopenharmony_ci	}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	return 0;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_cinla_put_failure:
61062306a36Sopenharmony_ci	nla_nest_cancel(skb, tb);
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_cinla_info_failure:
61362306a36Sopenharmony_ci	return -EMSGSIZE;
61462306a36Sopenharmony_ci}
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ciint br_cfm_status_fill_info(struct sk_buff *skb,
61762306a36Sopenharmony_ci			    struct net_bridge *br,
61862306a36Sopenharmony_ci			    bool getlink)
61962306a36Sopenharmony_ci{
62062306a36Sopenharmony_ci	struct br_cfm_peer_mep *peer_mep;
62162306a36Sopenharmony_ci	struct br_cfm_mep *mep;
62262306a36Sopenharmony_ci	struct nlattr *tb;
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	hlist_for_each_entry_rcu(mep, &br->mep_list, head) {
62562306a36Sopenharmony_ci		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INFO);
62662306a36Sopenharmony_ci		if (!tb)
62762306a36Sopenharmony_ci			goto nla_info_failure;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE,
63062306a36Sopenharmony_ci				mep->instance))
63162306a36Sopenharmony_ci			goto nla_put_failure;
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci		if (nla_put_u32(skb,
63462306a36Sopenharmony_ci				IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN,
63562306a36Sopenharmony_ci				mep->status.opcode_unexp_seen))
63662306a36Sopenharmony_ci			goto nla_put_failure;
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci		if (nla_put_u32(skb,
63962306a36Sopenharmony_ci				IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN,
64062306a36Sopenharmony_ci				mep->status.version_unexp_seen))
64162306a36Sopenharmony_ci			goto nla_put_failure;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci		if (nla_put_u32(skb,
64462306a36Sopenharmony_ci				IFLA_BRIDGE_CFM_MEP_STATUS_RX_LEVEL_LOW_SEEN,
64562306a36Sopenharmony_ci				mep->status.rx_level_low_seen))
64662306a36Sopenharmony_ci			goto nla_put_failure;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci		/* Only clear if this is a GETLINK */
64962306a36Sopenharmony_ci		if (getlink) {
65062306a36Sopenharmony_ci			/* Clear all 'seen' indications */
65162306a36Sopenharmony_ci			mep->status.opcode_unexp_seen = false;
65262306a36Sopenharmony_ci			mep->status.version_unexp_seen = false;
65362306a36Sopenharmony_ci			mep->status.rx_level_low_seen = false;
65462306a36Sopenharmony_ci		}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci		nla_nest_end(skb, tb);
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci		hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) {
65962306a36Sopenharmony_ci			tb = nla_nest_start(skb,
66062306a36Sopenharmony_ci					    IFLA_BRIDGE_CFM_CC_PEER_STATUS_INFO);
66162306a36Sopenharmony_ci			if (!tb)
66262306a36Sopenharmony_ci				goto nla_info_failure;
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci			if (nla_put_u32(skb,
66562306a36Sopenharmony_ci					IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE,
66662306a36Sopenharmony_ci					mep->instance))
66762306a36Sopenharmony_ci				goto nla_put_failure;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci			if (nla_put_u32(skb,
67062306a36Sopenharmony_ci					IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID,
67162306a36Sopenharmony_ci					peer_mep->mepid))
67262306a36Sopenharmony_ci				goto nla_put_failure;
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci			if (nla_put_u32(skb,
67562306a36Sopenharmony_ci					IFLA_BRIDGE_CFM_CC_PEER_STATUS_CCM_DEFECT,
67662306a36Sopenharmony_ci					peer_mep->cc_status.ccm_defect))
67762306a36Sopenharmony_ci				goto nla_put_failure;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci			if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI,
68062306a36Sopenharmony_ci					peer_mep->cc_status.rdi))
68162306a36Sopenharmony_ci				goto nla_put_failure;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci			if (nla_put_u8(skb,
68462306a36Sopenharmony_ci				       IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE,
68562306a36Sopenharmony_ci				       peer_mep->cc_status.port_tlv_value))
68662306a36Sopenharmony_ci				goto nla_put_failure;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci			if (nla_put_u8(skb,
68962306a36Sopenharmony_ci				       IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE,
69062306a36Sopenharmony_ci				       peer_mep->cc_status.if_tlv_value))
69162306a36Sopenharmony_ci				goto nla_put_failure;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci			if (nla_put_u32(skb,
69462306a36Sopenharmony_ci					IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN,
69562306a36Sopenharmony_ci					peer_mep->cc_status.seen))
69662306a36Sopenharmony_ci				goto nla_put_failure;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci			if (nla_put_u32(skb,
69962306a36Sopenharmony_ci					IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN,
70062306a36Sopenharmony_ci					peer_mep->cc_status.tlv_seen))
70162306a36Sopenharmony_ci				goto nla_put_failure;
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci			if (nla_put_u32(skb,
70462306a36Sopenharmony_ci					IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEQ_UNEXP_SEEN,
70562306a36Sopenharmony_ci					peer_mep->cc_status.seq_unexp_seen))
70662306a36Sopenharmony_ci				goto nla_put_failure;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci			if (getlink) { /* Only clear if this is a GETLINK */
70962306a36Sopenharmony_ci				/* Clear all 'seen' indications */
71062306a36Sopenharmony_ci				peer_mep->cc_status.seen = false;
71162306a36Sopenharmony_ci				peer_mep->cc_status.tlv_seen = false;
71262306a36Sopenharmony_ci				peer_mep->cc_status.seq_unexp_seen = false;
71362306a36Sopenharmony_ci			}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci			nla_nest_end(skb, tb);
71662306a36Sopenharmony_ci		}
71762306a36Sopenharmony_ci	}
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	return 0;
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_cinla_put_failure:
72262306a36Sopenharmony_ci	nla_nest_cancel(skb, tb);
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_cinla_info_failure:
72562306a36Sopenharmony_ci	return -EMSGSIZE;
72662306a36Sopenharmony_ci}
727