xref: /openbmc/linux/net/bridge/br_cfm_netlink.c (revision daa24d20)
12be665c3SHenrik Bjoernlund // SPDX-License-Identifier: GPL-2.0-or-later
22be665c3SHenrik Bjoernlund 
32be665c3SHenrik Bjoernlund #include <net/genetlink.h>
42be665c3SHenrik Bjoernlund 
52be665c3SHenrik Bjoernlund #include "br_private.h"
62be665c3SHenrik Bjoernlund #include "br_private_cfm.h"
72be665c3SHenrik Bjoernlund 
82be665c3SHenrik Bjoernlund static const struct nla_policy
92be665c3SHenrik Bjoernlund br_cfm_mep_create_policy[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1] = {
102be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CREATE_UNSPEC]	= { .type = NLA_REJECT },
112be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]	= { .type = NLA_U32 },
122be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]	= { .type = NLA_U32 },
132be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]	= { .type = NLA_U32 },
142be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]	= { .type = NLA_U32 },
152be665c3SHenrik Bjoernlund };
162be665c3SHenrik Bjoernlund 
172be665c3SHenrik Bjoernlund static const struct nla_policy
182be665c3SHenrik Bjoernlund br_cfm_mep_delete_policy[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1] = {
192be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_DELETE_UNSPEC]	= { .type = NLA_REJECT },
202be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]	= { .type = NLA_U32 },
212be665c3SHenrik Bjoernlund };
222be665c3SHenrik Bjoernlund 
232be665c3SHenrik Bjoernlund static const struct nla_policy
242be665c3SHenrik Bjoernlund br_cfm_mep_config_policy[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1] = {
252be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CONFIG_UNSPEC]	 = { .type = NLA_REJECT },
262be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]	 = { .type = NLA_U32 },
272be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC] = NLA_POLICY_ETH_ADDR,
282be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]	 = NLA_POLICY_MAX(NLA_U32, 7),
292be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]	 = NLA_POLICY_MAX(NLA_U32, 0x1FFF),
302be665c3SHenrik Bjoernlund };
312be665c3SHenrik Bjoernlund 
322be665c3SHenrik Bjoernlund static const struct nla_policy
332be665c3SHenrik Bjoernlund br_cfm_cc_config_policy[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1] = {
342be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC]	 = { .type = NLA_REJECT },
352be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]	 = { .type = NLA_U32 },
362be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]	 = { .type = NLA_U32 },
372be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = { .type = NLA_U32 },
382be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]	 = {
392be665c3SHenrik Bjoernlund 	.type = NLA_BINARY, .len = CFM_MAID_LENGTH },
402be665c3SHenrik Bjoernlund };
412be665c3SHenrik Bjoernlund 
422be665c3SHenrik Bjoernlund static const struct nla_policy
432be665c3SHenrik Bjoernlund br_cfm_cc_peer_mep_policy[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1] = {
442be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_PEER_MEP_UNSPEC]	= { .type = NLA_REJECT },
452be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]	= { .type = NLA_U32 },
462be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_PEER_MEPID]		= NLA_POLICY_MAX(NLA_U32, 0x1FFF),
472be665c3SHenrik Bjoernlund };
482be665c3SHenrik Bjoernlund 
492be665c3SHenrik Bjoernlund static const struct nla_policy
502be665c3SHenrik Bjoernlund br_cfm_cc_rdi_policy[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1] = {
512be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_RDI_UNSPEC]		= { .type = NLA_REJECT },
522be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]	= { .type = NLA_U32 },
532be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_RDI_RDI]		= { .type = NLA_U32 },
542be665c3SHenrik Bjoernlund };
552be665c3SHenrik Bjoernlund 
562be665c3SHenrik Bjoernlund static const struct nla_policy
572be665c3SHenrik Bjoernlund br_cfm_cc_ccm_tx_policy[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1] = {
582be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CCM_TX_UNSPEC]	   = { .type = NLA_REJECT },
592be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]	   = { .type = NLA_U32 },
602be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]	   = NLA_POLICY_ETH_ADDR,
612be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]  = { .type = NLA_U32 },
622be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]	   = { .type = NLA_U32 },
632be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]	   = { .type = NLA_U32 },
642be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]   = { .type = NLA_U8 },
652be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]	   = { .type = NLA_U32 },
662be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE] = { .type = NLA_U8 },
672be665c3SHenrik Bjoernlund };
682be665c3SHenrik Bjoernlund 
692be665c3SHenrik Bjoernlund static const struct nla_policy
702be665c3SHenrik Bjoernlund br_cfm_policy[IFLA_BRIDGE_CFM_MAX + 1] = {
712be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_UNSPEC]		= { .type = NLA_REJECT },
722be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CREATE]		=
732be665c3SHenrik Bjoernlund 				NLA_POLICY_NESTED(br_cfm_mep_create_policy),
742be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_DELETE]		=
752be665c3SHenrik Bjoernlund 				NLA_POLICY_NESTED(br_cfm_mep_delete_policy),
762be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_MEP_CONFIG]		=
772be665c3SHenrik Bjoernlund 				NLA_POLICY_NESTED(br_cfm_mep_config_policy),
782be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CONFIG]		=
792be665c3SHenrik Bjoernlund 				NLA_POLICY_NESTED(br_cfm_cc_config_policy),
802be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]	=
812be665c3SHenrik Bjoernlund 				NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy),
822be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]	=
832be665c3SHenrik Bjoernlund 				NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy),
842be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_RDI]		=
852be665c3SHenrik Bjoernlund 				NLA_POLICY_NESTED(br_cfm_cc_rdi_policy),
862be665c3SHenrik Bjoernlund 	[IFLA_BRIDGE_CFM_CC_CCM_TX]		=
872be665c3SHenrik Bjoernlund 				NLA_POLICY_NESTED(br_cfm_cc_ccm_tx_policy),
882be665c3SHenrik Bjoernlund };
892be665c3SHenrik Bjoernlund 
br_mep_create_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)902be665c3SHenrik Bjoernlund static int br_mep_create_parse(struct net_bridge *br, struct nlattr *attr,
912be665c3SHenrik Bjoernlund 			       struct netlink_ext_ack *extack)
922be665c3SHenrik Bjoernlund {
932be665c3SHenrik Bjoernlund 	struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1];
942be665c3SHenrik Bjoernlund 	struct br_cfm_mep_create create;
952be665c3SHenrik Bjoernlund 	u32 instance;
962be665c3SHenrik Bjoernlund 	int err;
972be665c3SHenrik Bjoernlund 
982be665c3SHenrik Bjoernlund 	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CREATE_MAX, attr,
992be665c3SHenrik Bjoernlund 			       br_cfm_mep_create_policy, extack);
1002be665c3SHenrik Bjoernlund 	if (err)
1012be665c3SHenrik Bjoernlund 		return err;
1022be665c3SHenrik Bjoernlund 
1032be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]) {
1042be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
1052be665c3SHenrik Bjoernlund 		return -EINVAL;
1062be665c3SHenrik Bjoernlund 	}
1072be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]) {
1082be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing DOMAIN attribute");
1092be665c3SHenrik Bjoernlund 		return -EINVAL;
1102be665c3SHenrik Bjoernlund 	}
1112be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]) {
1122be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing DIRECTION attribute");
1132be665c3SHenrik Bjoernlund 		return -EINVAL;
1142be665c3SHenrik Bjoernlund 	}
1152be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]) {
1162be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing IFINDEX attribute");
1172be665c3SHenrik Bjoernlund 		return -EINVAL;
1182be665c3SHenrik Bjoernlund 	}
1192be665c3SHenrik Bjoernlund 
1202be665c3SHenrik Bjoernlund 	memset(&create, 0, sizeof(create));
1212be665c3SHenrik Bjoernlund 
1222be665c3SHenrik Bjoernlund 	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]);
1232be665c3SHenrik Bjoernlund 	create.domain = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]);
1242be665c3SHenrik Bjoernlund 	create.direction = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]);
1252be665c3SHenrik Bjoernlund 	create.ifindex = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]);
1262be665c3SHenrik Bjoernlund 
1272be665c3SHenrik Bjoernlund 	return br_cfm_mep_create(br, instance, &create, extack);
1282be665c3SHenrik Bjoernlund }
1292be665c3SHenrik Bjoernlund 
br_mep_delete_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)1302be665c3SHenrik Bjoernlund static int br_mep_delete_parse(struct net_bridge *br, struct nlattr *attr,
1312be665c3SHenrik Bjoernlund 			       struct netlink_ext_ack *extack)
1322be665c3SHenrik Bjoernlund {
1332be665c3SHenrik Bjoernlund 	struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1];
1342be665c3SHenrik Bjoernlund 	u32 instance;
1352be665c3SHenrik Bjoernlund 	int err;
1362be665c3SHenrik Bjoernlund 
1372be665c3SHenrik Bjoernlund 	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_DELETE_MAX, attr,
1382be665c3SHenrik Bjoernlund 			       br_cfm_mep_delete_policy, extack);
1392be665c3SHenrik Bjoernlund 	if (err)
1402be665c3SHenrik Bjoernlund 		return err;
1412be665c3SHenrik Bjoernlund 
1422be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]) {
1432be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack,
1442be665c3SHenrik Bjoernlund 				   "Missing INSTANCE attribute");
1452be665c3SHenrik Bjoernlund 		return -EINVAL;
1462be665c3SHenrik Bjoernlund 	}
1472be665c3SHenrik Bjoernlund 
1482be665c3SHenrik Bjoernlund 	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]);
1492be665c3SHenrik Bjoernlund 
1502be665c3SHenrik Bjoernlund 	return br_cfm_mep_delete(br, instance, extack);
1512be665c3SHenrik Bjoernlund }
1522be665c3SHenrik Bjoernlund 
br_mep_config_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)1532be665c3SHenrik Bjoernlund static int br_mep_config_parse(struct net_bridge *br, struct nlattr *attr,
1542be665c3SHenrik Bjoernlund 			       struct netlink_ext_ack *extack)
1552be665c3SHenrik Bjoernlund {
1562be665c3SHenrik Bjoernlund 	struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1];
1572be665c3SHenrik Bjoernlund 	struct br_cfm_mep_config config;
1582be665c3SHenrik Bjoernlund 	u32 instance;
1592be665c3SHenrik Bjoernlund 	int err;
1602be665c3SHenrik Bjoernlund 
1612be665c3SHenrik Bjoernlund 	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CONFIG_MAX, attr,
1622be665c3SHenrik Bjoernlund 			       br_cfm_mep_config_policy, extack);
1632be665c3SHenrik Bjoernlund 	if (err)
1642be665c3SHenrik Bjoernlund 		return err;
1652be665c3SHenrik Bjoernlund 
1662be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]) {
1672be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
1682be665c3SHenrik Bjoernlund 		return -EINVAL;
1692be665c3SHenrik Bjoernlund 	}
1702be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC]) {
1712be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing UNICAST_MAC attribute");
1722be665c3SHenrik Bjoernlund 		return -EINVAL;
1732be665c3SHenrik Bjoernlund 	}
1742be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]) {
1752be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing MDLEVEL attribute");
1762be665c3SHenrik Bjoernlund 		return -EINVAL;
1772be665c3SHenrik Bjoernlund 	}
1782be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]) {
1792be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing MEPID attribute");
1802be665c3SHenrik Bjoernlund 		return -EINVAL;
1812be665c3SHenrik Bjoernlund 	}
1822be665c3SHenrik Bjoernlund 
1832be665c3SHenrik Bjoernlund 	memset(&config, 0, sizeof(config));
1842be665c3SHenrik Bjoernlund 
1852be665c3SHenrik Bjoernlund 	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]);
1862be665c3SHenrik Bjoernlund 	nla_memcpy(&config.unicast_mac.addr,
1872be665c3SHenrik Bjoernlund 		   tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC],
1882be665c3SHenrik Bjoernlund 		   sizeof(config.unicast_mac.addr));
1892be665c3SHenrik Bjoernlund 	config.mdlevel = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]);
1902be665c3SHenrik Bjoernlund 	config.mepid = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]);
1912be665c3SHenrik Bjoernlund 
1922be665c3SHenrik Bjoernlund 	return br_cfm_mep_config_set(br, instance, &config, extack);
1932be665c3SHenrik Bjoernlund }
1942be665c3SHenrik Bjoernlund 
br_cc_config_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)1952be665c3SHenrik Bjoernlund static int br_cc_config_parse(struct net_bridge *br, struct nlattr *attr,
1962be665c3SHenrik Bjoernlund 			      struct netlink_ext_ack *extack)
1972be665c3SHenrik Bjoernlund {
1982be665c3SHenrik Bjoernlund 	struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1];
1992be665c3SHenrik Bjoernlund 	struct br_cfm_cc_config config;
2002be665c3SHenrik Bjoernlund 	u32 instance;
2012be665c3SHenrik Bjoernlund 	int err;
2022be665c3SHenrik Bjoernlund 
2032be665c3SHenrik Bjoernlund 	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CONFIG_MAX, attr,
2042be665c3SHenrik Bjoernlund 			       br_cfm_cc_config_policy, extack);
2052be665c3SHenrik Bjoernlund 	if (err)
2062be665c3SHenrik Bjoernlund 		return err;
2072be665c3SHenrik Bjoernlund 
2082be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]) {
2092be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
2102be665c3SHenrik Bjoernlund 		return -EINVAL;
2112be665c3SHenrik Bjoernlund 	}
2122be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]) {
2132be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing ENABLE attribute");
2142be665c3SHenrik Bjoernlund 		return -EINVAL;
2152be665c3SHenrik Bjoernlund 	}
2162be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]) {
2172be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing INTERVAL attribute");
2182be665c3SHenrik Bjoernlund 		return -EINVAL;
2192be665c3SHenrik Bjoernlund 	}
2202be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]) {
2212be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing MAID attribute");
2222be665c3SHenrik Bjoernlund 		return -EINVAL;
2232be665c3SHenrik Bjoernlund 	}
2242be665c3SHenrik Bjoernlund 
2252be665c3SHenrik Bjoernlund 	memset(&config, 0, sizeof(config));
2262be665c3SHenrik Bjoernlund 
2272be665c3SHenrik Bjoernlund 	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]);
2282be665c3SHenrik Bjoernlund 	config.enable = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]);
2292be665c3SHenrik Bjoernlund 	config.exp_interval = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]);
2302be665c3SHenrik Bjoernlund 	nla_memcpy(&config.exp_maid.data, tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID],
2312be665c3SHenrik Bjoernlund 		   sizeof(config.exp_maid.data));
2322be665c3SHenrik Bjoernlund 
2332be665c3SHenrik Bjoernlund 	return br_cfm_cc_config_set(br, instance, &config, extack);
2342be665c3SHenrik Bjoernlund }
2352be665c3SHenrik Bjoernlund 
br_cc_peer_mep_add_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)2362be665c3SHenrik Bjoernlund static int br_cc_peer_mep_add_parse(struct net_bridge *br, struct nlattr *attr,
2372be665c3SHenrik Bjoernlund 				    struct netlink_ext_ack *extack)
2382be665c3SHenrik Bjoernlund {
2392be665c3SHenrik Bjoernlund 	struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
2402be665c3SHenrik Bjoernlund 	u32 instance, peer_mep_id;
2412be665c3SHenrik Bjoernlund 	int err;
2422be665c3SHenrik Bjoernlund 
2432be665c3SHenrik Bjoernlund 	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr,
2442be665c3SHenrik Bjoernlund 			       br_cfm_cc_peer_mep_policy, extack);
2452be665c3SHenrik Bjoernlund 	if (err)
2462be665c3SHenrik Bjoernlund 		return err;
2472be665c3SHenrik Bjoernlund 
2482be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
2492be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
2502be665c3SHenrik Bjoernlund 		return -EINVAL;
2512be665c3SHenrik Bjoernlund 	}
2522be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
2532be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
2542be665c3SHenrik Bjoernlund 		return -EINVAL;
2552be665c3SHenrik Bjoernlund 	}
2562be665c3SHenrik Bjoernlund 
2572be665c3SHenrik Bjoernlund 	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]);
2582be665c3SHenrik Bjoernlund 	peer_mep_id =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]);
2592be665c3SHenrik Bjoernlund 
2602be665c3SHenrik Bjoernlund 	return br_cfm_cc_peer_mep_add(br, instance, peer_mep_id, extack);
2612be665c3SHenrik Bjoernlund }
2622be665c3SHenrik Bjoernlund 
br_cc_peer_mep_remove_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)2632be665c3SHenrik Bjoernlund static int br_cc_peer_mep_remove_parse(struct net_bridge *br, struct nlattr *attr,
2642be665c3SHenrik Bjoernlund 				       struct netlink_ext_ack *extack)
2652be665c3SHenrik Bjoernlund {
2662be665c3SHenrik Bjoernlund 	struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
2672be665c3SHenrik Bjoernlund 	u32 instance, peer_mep_id;
2682be665c3SHenrik Bjoernlund 	int err;
2692be665c3SHenrik Bjoernlund 
2702be665c3SHenrik Bjoernlund 	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr,
2712be665c3SHenrik Bjoernlund 			       br_cfm_cc_peer_mep_policy, extack);
2722be665c3SHenrik Bjoernlund 	if (err)
2732be665c3SHenrik Bjoernlund 		return err;
2742be665c3SHenrik Bjoernlund 
2752be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
2762be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
2772be665c3SHenrik Bjoernlund 		return -EINVAL;
2782be665c3SHenrik Bjoernlund 	}
2792be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
2802be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
2812be665c3SHenrik Bjoernlund 		return -EINVAL;
2822be665c3SHenrik Bjoernlund 	}
2832be665c3SHenrik Bjoernlund 
2842be665c3SHenrik Bjoernlund 	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]);
2852be665c3SHenrik Bjoernlund 	peer_mep_id =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]);
2862be665c3SHenrik Bjoernlund 
2872be665c3SHenrik Bjoernlund 	return br_cfm_cc_peer_mep_remove(br, instance, peer_mep_id, extack);
2882be665c3SHenrik Bjoernlund }
2892be665c3SHenrik Bjoernlund 
br_cc_rdi_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)2902be665c3SHenrik Bjoernlund static int br_cc_rdi_parse(struct net_bridge *br, struct nlattr *attr,
2912be665c3SHenrik Bjoernlund 			   struct netlink_ext_ack *extack)
2922be665c3SHenrik Bjoernlund {
2932be665c3SHenrik Bjoernlund 	struct nlattr *tb[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1];
2942be665c3SHenrik Bjoernlund 	u32 instance, rdi;
2952be665c3SHenrik Bjoernlund 	int err;
2962be665c3SHenrik Bjoernlund 
2972be665c3SHenrik Bjoernlund 	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_RDI_MAX, attr,
2982be665c3SHenrik Bjoernlund 			       br_cfm_cc_rdi_policy, extack);
2992be665c3SHenrik Bjoernlund 	if (err)
3002be665c3SHenrik Bjoernlund 		return err;
3012be665c3SHenrik Bjoernlund 
3022be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]) {
3032be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
3042be665c3SHenrik Bjoernlund 		return -EINVAL;
3052be665c3SHenrik Bjoernlund 	}
3062be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]) {
3072be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing RDI attribute");
3082be665c3SHenrik Bjoernlund 		return -EINVAL;
3092be665c3SHenrik Bjoernlund 	}
3102be665c3SHenrik Bjoernlund 
3112be665c3SHenrik Bjoernlund 	instance =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]);
3122be665c3SHenrik Bjoernlund 	rdi =  nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]);
3132be665c3SHenrik Bjoernlund 
3142be665c3SHenrik Bjoernlund 	return br_cfm_cc_rdi_set(br, instance, rdi, extack);
3152be665c3SHenrik Bjoernlund }
3162be665c3SHenrik Bjoernlund 
br_cc_ccm_tx_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)3172be665c3SHenrik Bjoernlund static int br_cc_ccm_tx_parse(struct net_bridge *br, struct nlattr *attr,
3182be665c3SHenrik Bjoernlund 			      struct netlink_ext_ack *extack)
3192be665c3SHenrik Bjoernlund {
3202be665c3SHenrik Bjoernlund 	struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1];
3212be665c3SHenrik Bjoernlund 	struct br_cfm_cc_ccm_tx_info tx_info;
3222be665c3SHenrik Bjoernlund 	u32 instance;
3232be665c3SHenrik Bjoernlund 	int err;
3242be665c3SHenrik Bjoernlund 
3252be665c3SHenrik Bjoernlund 	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CCM_TX_MAX, attr,
3262be665c3SHenrik Bjoernlund 			       br_cfm_cc_ccm_tx_policy, extack);
3272be665c3SHenrik Bjoernlund 	if (err)
3282be665c3SHenrik Bjoernlund 		return err;
3292be665c3SHenrik Bjoernlund 
3302be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]) {
3312be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
3322be665c3SHenrik Bjoernlund 		return -EINVAL;
3332be665c3SHenrik Bjoernlund 	}
3342be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]) {
3352be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing DMAC attribute");
3362be665c3SHenrik Bjoernlund 		return -EINVAL;
3372be665c3SHenrik Bjoernlund 	}
3382be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]) {
3392be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing SEQ_NO_UPDATE attribute");
3402be665c3SHenrik Bjoernlund 		return -EINVAL;
3412be665c3SHenrik Bjoernlund 	}
3422be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]) {
3432be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing PERIOD attribute");
3442be665c3SHenrik Bjoernlund 		return -EINVAL;
3452be665c3SHenrik Bjoernlund 	}
3462be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]) {
3472be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV attribute");
3482be665c3SHenrik Bjoernlund 		return -EINVAL;
3492be665c3SHenrik Bjoernlund 	}
3502be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]) {
3512be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV_VALUE attribute");
3522be665c3SHenrik Bjoernlund 		return -EINVAL;
3532be665c3SHenrik Bjoernlund 	}
3542be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]) {
3552be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV attribute");
3562be665c3SHenrik Bjoernlund 		return -EINVAL;
3572be665c3SHenrik Bjoernlund 	}
3582be665c3SHenrik Bjoernlund 	if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]) {
3592be665c3SHenrik Bjoernlund 		NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV_VALUE attribute");
3602be665c3SHenrik Bjoernlund 		return -EINVAL;
3612be665c3SHenrik Bjoernlund 	}
3622be665c3SHenrik Bjoernlund 
3632be665c3SHenrik Bjoernlund 	memset(&tx_info, 0, sizeof(tx_info));
3642be665c3SHenrik Bjoernlund 
365*daa24d20SLin Ma 	instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]);
3662be665c3SHenrik Bjoernlund 	nla_memcpy(&tx_info.dmac.addr,
3672be665c3SHenrik Bjoernlund 		   tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC],
3682be665c3SHenrik Bjoernlund 		   sizeof(tx_info.dmac.addr));
3692be665c3SHenrik Bjoernlund 	tx_info.seq_no_update = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]);
3702be665c3SHenrik Bjoernlund 	tx_info.period = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]);
3712be665c3SHenrik Bjoernlund 	tx_info.if_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]);
3722be665c3SHenrik Bjoernlund 	tx_info.if_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]);
3732be665c3SHenrik Bjoernlund 	tx_info.port_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]);
3742be665c3SHenrik Bjoernlund 	tx_info.port_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]);
3752be665c3SHenrik Bjoernlund 
3762be665c3SHenrik Bjoernlund 	return br_cfm_cc_ccm_tx(br, instance, &tx_info, extack);
3772be665c3SHenrik Bjoernlund }
3782be665c3SHenrik Bjoernlund 
br_cfm_parse(struct net_bridge * br,struct net_bridge_port * p,struct nlattr * attr,int cmd,struct netlink_ext_ack * extack)3792be665c3SHenrik Bjoernlund int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,
3802be665c3SHenrik Bjoernlund 		 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
3812be665c3SHenrik Bjoernlund {
3822be665c3SHenrik Bjoernlund 	struct nlattr *tb[IFLA_BRIDGE_CFM_MAX + 1];
3832be665c3SHenrik Bjoernlund 	int err;
3842be665c3SHenrik Bjoernlund 
3852be665c3SHenrik Bjoernlund 	/* When this function is called for a port then the br pointer is
3862be665c3SHenrik Bjoernlund 	 * invalid, therefor set the br to point correctly
3872be665c3SHenrik Bjoernlund 	 */
3882be665c3SHenrik Bjoernlund 	if (p)
3892be665c3SHenrik Bjoernlund 		br = p->br;
3902be665c3SHenrik Bjoernlund 
3912be665c3SHenrik Bjoernlund 	err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MAX, attr,
3922be665c3SHenrik Bjoernlund 			       br_cfm_policy, extack);
3932be665c3SHenrik Bjoernlund 	if (err)
3942be665c3SHenrik Bjoernlund 		return err;
3952be665c3SHenrik Bjoernlund 
3962be665c3SHenrik Bjoernlund 	if (tb[IFLA_BRIDGE_CFM_MEP_CREATE]) {
3972be665c3SHenrik Bjoernlund 		err = br_mep_create_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CREATE],
3982be665c3SHenrik Bjoernlund 					  extack);
3992be665c3SHenrik Bjoernlund 		if (err)
4002be665c3SHenrik Bjoernlund 			return err;
4012be665c3SHenrik Bjoernlund 	}
4022be665c3SHenrik Bjoernlund 
4032be665c3SHenrik Bjoernlund 	if (tb[IFLA_BRIDGE_CFM_MEP_DELETE]) {
4042be665c3SHenrik Bjoernlund 		err = br_mep_delete_parse(br, tb[IFLA_BRIDGE_CFM_MEP_DELETE],
4052be665c3SHenrik Bjoernlund 					  extack);
4062be665c3SHenrik Bjoernlund 		if (err)
4072be665c3SHenrik Bjoernlund 			return err;
4082be665c3SHenrik Bjoernlund 	}
4092be665c3SHenrik Bjoernlund 
4102be665c3SHenrik Bjoernlund 	if (tb[IFLA_BRIDGE_CFM_MEP_CONFIG]) {
4112be665c3SHenrik Bjoernlund 		err = br_mep_config_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CONFIG],
4122be665c3SHenrik Bjoernlund 					  extack);
4132be665c3SHenrik Bjoernlund 		if (err)
4142be665c3SHenrik Bjoernlund 			return err;
4152be665c3SHenrik Bjoernlund 	}
4162be665c3SHenrik Bjoernlund 
4172be665c3SHenrik Bjoernlund 	if (tb[IFLA_BRIDGE_CFM_CC_CONFIG]) {
4182be665c3SHenrik Bjoernlund 		err = br_cc_config_parse(br, tb[IFLA_BRIDGE_CFM_CC_CONFIG],
4192be665c3SHenrik Bjoernlund 					 extack);
4202be665c3SHenrik Bjoernlund 		if (err)
4212be665c3SHenrik Bjoernlund 			return err;
4222be665c3SHenrik Bjoernlund 	}
4232be665c3SHenrik Bjoernlund 
4242be665c3SHenrik Bjoernlund 	if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]) {
4252be665c3SHenrik Bjoernlund 		err = br_cc_peer_mep_add_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD],
4262be665c3SHenrik Bjoernlund 					       extack);
4272be665c3SHenrik Bjoernlund 		if (err)
4282be665c3SHenrik Bjoernlund 			return err;
4292be665c3SHenrik Bjoernlund 	}
4302be665c3SHenrik Bjoernlund 
4312be665c3SHenrik Bjoernlund 	if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]) {
4322be665c3SHenrik Bjoernlund 		err = br_cc_peer_mep_remove_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE],
4332be665c3SHenrik Bjoernlund 						  extack);
4342be665c3SHenrik Bjoernlund 		if (err)
4352be665c3SHenrik Bjoernlund 			return err;
4362be665c3SHenrik Bjoernlund 	}
4372be665c3SHenrik Bjoernlund 
4382be665c3SHenrik Bjoernlund 	if (tb[IFLA_BRIDGE_CFM_CC_RDI]) {
4392be665c3SHenrik Bjoernlund 		err = br_cc_rdi_parse(br, tb[IFLA_BRIDGE_CFM_CC_RDI],
4402be665c3SHenrik Bjoernlund 				      extack);
4412be665c3SHenrik Bjoernlund 		if (err)
4422be665c3SHenrik Bjoernlund 			return err;
4432be665c3SHenrik Bjoernlund 	}
4442be665c3SHenrik Bjoernlund 
4452be665c3SHenrik Bjoernlund 	if (tb[IFLA_BRIDGE_CFM_CC_CCM_TX]) {
4462be665c3SHenrik Bjoernlund 		err = br_cc_ccm_tx_parse(br, tb[IFLA_BRIDGE_CFM_CC_CCM_TX],
4472be665c3SHenrik Bjoernlund 					 extack);
4482be665c3SHenrik Bjoernlund 		if (err)
4492be665c3SHenrik Bjoernlund 			return err;
4502be665c3SHenrik Bjoernlund 	}
4512be665c3SHenrik Bjoernlund 
4522be665c3SHenrik Bjoernlund 	return 0;
4532be665c3SHenrik Bjoernlund }
4545e312fc0SHenrik Bjoernlund 
br_cfm_config_fill_info(struct sk_buff * skb,struct net_bridge * br)4555e312fc0SHenrik Bjoernlund int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br)
4565e312fc0SHenrik Bjoernlund {
4575e312fc0SHenrik Bjoernlund 	struct br_cfm_peer_mep *peer_mep;
4585e312fc0SHenrik Bjoernlund 	struct br_cfm_mep *mep;
4595e312fc0SHenrik Bjoernlund 	struct nlattr *tb;
4605e312fc0SHenrik Bjoernlund 
4615e312fc0SHenrik Bjoernlund 	hlist_for_each_entry_rcu(mep, &br->mep_list, head) {
4625e312fc0SHenrik Bjoernlund 		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INFO);
4635e312fc0SHenrik Bjoernlund 		if (!tb)
4645e312fc0SHenrik Bjoernlund 			goto nla_info_failure;
4655e312fc0SHenrik Bjoernlund 
4665e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE,
4675e312fc0SHenrik Bjoernlund 				mep->instance))
4685e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
4695e312fc0SHenrik Bjoernlund 
4705e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN,
4715e312fc0SHenrik Bjoernlund 				mep->create.domain))
4725e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
4735e312fc0SHenrik Bjoernlund 
4745e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION,
4755e312fc0SHenrik Bjoernlund 				mep->create.direction))
4765e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
4775e312fc0SHenrik Bjoernlund 
4785e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX,
4795e312fc0SHenrik Bjoernlund 				mep->create.ifindex))
4805e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
4815e312fc0SHenrik Bjoernlund 
4825e312fc0SHenrik Bjoernlund 		nla_nest_end(skb, tb);
4835e312fc0SHenrik Bjoernlund 
4845e312fc0SHenrik Bjoernlund 		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INFO);
4855e312fc0SHenrik Bjoernlund 
4865e312fc0SHenrik Bjoernlund 		if (!tb)
4875e312fc0SHenrik Bjoernlund 			goto nla_info_failure;
4885e312fc0SHenrik Bjoernlund 
4895e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE,
4905e312fc0SHenrik Bjoernlund 				mep->instance))
4915e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
4925e312fc0SHenrik Bjoernlund 
4935e312fc0SHenrik Bjoernlund 		if (nla_put(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC,
4945e312fc0SHenrik Bjoernlund 			    sizeof(mep->config.unicast_mac.addr),
4955e312fc0SHenrik Bjoernlund 			    mep->config.unicast_mac.addr))
4965e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
4975e312fc0SHenrik Bjoernlund 
4985e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL,
4995e312fc0SHenrik Bjoernlund 				mep->config.mdlevel))
5005e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5015e312fc0SHenrik Bjoernlund 
5025e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID,
5035e312fc0SHenrik Bjoernlund 				mep->config.mepid))
5045e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5055e312fc0SHenrik Bjoernlund 
5065e312fc0SHenrik Bjoernlund 		nla_nest_end(skb, tb);
5075e312fc0SHenrik Bjoernlund 
5085e312fc0SHenrik Bjoernlund 		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INFO);
5095e312fc0SHenrik Bjoernlund 
5105e312fc0SHenrik Bjoernlund 		if (!tb)
5115e312fc0SHenrik Bjoernlund 			goto nla_info_failure;
5125e312fc0SHenrik Bjoernlund 
5135e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE,
5145e312fc0SHenrik Bjoernlund 				mep->instance))
5155e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5165e312fc0SHenrik Bjoernlund 
5175e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE,
5185e312fc0SHenrik Bjoernlund 				mep->cc_config.enable))
5195e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5205e312fc0SHenrik Bjoernlund 
5215e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL,
5225e312fc0SHenrik Bjoernlund 				mep->cc_config.exp_interval))
5235e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5245e312fc0SHenrik Bjoernlund 
5255e312fc0SHenrik Bjoernlund 		if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID,
5265e312fc0SHenrik Bjoernlund 			    sizeof(mep->cc_config.exp_maid.data),
5275e312fc0SHenrik Bjoernlund 			    mep->cc_config.exp_maid.data))
5285e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5295e312fc0SHenrik Bjoernlund 
5305e312fc0SHenrik Bjoernlund 		nla_nest_end(skb, tb);
5315e312fc0SHenrik Bjoernlund 
5325e312fc0SHenrik Bjoernlund 		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_RDI_INFO);
5335e312fc0SHenrik Bjoernlund 
5345e312fc0SHenrik Bjoernlund 		if (!tb)
5355e312fc0SHenrik Bjoernlund 			goto nla_info_failure;
5365e312fc0SHenrik Bjoernlund 
5375e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_INSTANCE,
5385e312fc0SHenrik Bjoernlund 				mep->instance))
5395e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5405e312fc0SHenrik Bjoernlund 
5415e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_RDI,
5425e312fc0SHenrik Bjoernlund 				mep->rdi))
5435e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5445e312fc0SHenrik Bjoernlund 
5455e312fc0SHenrik Bjoernlund 		nla_nest_end(skb, tb);
5465e312fc0SHenrik Bjoernlund 
5475e312fc0SHenrik Bjoernlund 		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INFO);
5485e312fc0SHenrik Bjoernlund 
5495e312fc0SHenrik Bjoernlund 		if (!tb)
5505e312fc0SHenrik Bjoernlund 			goto nla_info_failure;
5515e312fc0SHenrik Bjoernlund 
5525e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE,
5535e312fc0SHenrik Bjoernlund 				mep->instance))
5545e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5555e312fc0SHenrik Bjoernlund 
5565e312fc0SHenrik Bjoernlund 		if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC,
5575e312fc0SHenrik Bjoernlund 			    sizeof(mep->cc_ccm_tx_info.dmac),
5585e312fc0SHenrik Bjoernlund 			    mep->cc_ccm_tx_info.dmac.addr))
5595e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5605e312fc0SHenrik Bjoernlund 
5615e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE,
5625e312fc0SHenrik Bjoernlund 				mep->cc_ccm_tx_info.seq_no_update))
5635e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5645e312fc0SHenrik Bjoernlund 
5655e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD,
5665e312fc0SHenrik Bjoernlund 				mep->cc_ccm_tx_info.period))
5675e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5685e312fc0SHenrik Bjoernlund 
5695e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV,
5705e312fc0SHenrik Bjoernlund 				mep->cc_ccm_tx_info.if_tlv))
5715e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5725e312fc0SHenrik Bjoernlund 
5735e312fc0SHenrik Bjoernlund 		if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE,
5745e312fc0SHenrik Bjoernlund 			       mep->cc_ccm_tx_info.if_tlv_value))
5755e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5765e312fc0SHenrik Bjoernlund 
5775e312fc0SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV,
5785e312fc0SHenrik Bjoernlund 				mep->cc_ccm_tx_info.port_tlv))
5795e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5805e312fc0SHenrik Bjoernlund 
5815e312fc0SHenrik Bjoernlund 		if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE,
5825e312fc0SHenrik Bjoernlund 			       mep->cc_ccm_tx_info.port_tlv_value))
5835e312fc0SHenrik Bjoernlund 			goto nla_put_failure;
5845e312fc0SHenrik Bjoernlund 
5855e312fc0SHenrik Bjoernlund 		nla_nest_end(skb, tb);
5865e312fc0SHenrik Bjoernlund 
5875e312fc0SHenrik Bjoernlund 		hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) {
5885e312fc0SHenrik Bjoernlund 			tb = nla_nest_start(skb,
5895e312fc0SHenrik Bjoernlund 					    IFLA_BRIDGE_CFM_CC_PEER_MEP_INFO);
5905e312fc0SHenrik Bjoernlund 
5915e312fc0SHenrik Bjoernlund 			if (!tb)
5925e312fc0SHenrik Bjoernlund 				goto nla_info_failure;
5935e312fc0SHenrik Bjoernlund 
5945e312fc0SHenrik Bjoernlund 			if (nla_put_u32(skb,
5955e312fc0SHenrik Bjoernlund 					IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE,
5965e312fc0SHenrik Bjoernlund 					mep->instance))
5975e312fc0SHenrik Bjoernlund 				goto nla_put_failure;
5985e312fc0SHenrik Bjoernlund 
5995e312fc0SHenrik Bjoernlund 			if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_MEPID,
6005e312fc0SHenrik Bjoernlund 					peer_mep->mepid))
6015e312fc0SHenrik Bjoernlund 				goto nla_put_failure;
6025e312fc0SHenrik Bjoernlund 
6035e312fc0SHenrik Bjoernlund 			nla_nest_end(skb, tb);
6045e312fc0SHenrik Bjoernlund 		}
6055e312fc0SHenrik Bjoernlund 	}
6065e312fc0SHenrik Bjoernlund 
6075e312fc0SHenrik Bjoernlund 	return 0;
6085e312fc0SHenrik Bjoernlund 
6095e312fc0SHenrik Bjoernlund nla_put_failure:
6105e312fc0SHenrik Bjoernlund 	nla_nest_cancel(skb, tb);
6115e312fc0SHenrik Bjoernlund 
6125e312fc0SHenrik Bjoernlund nla_info_failure:
6135e312fc0SHenrik Bjoernlund 	return -EMSGSIZE;
6145e312fc0SHenrik Bjoernlund }
615e77824d8SHenrik Bjoernlund 
br_cfm_status_fill_info(struct sk_buff * skb,struct net_bridge * br,bool getlink)616b6d0425bSHenrik Bjoernlund int br_cfm_status_fill_info(struct sk_buff *skb,
617b6d0425bSHenrik Bjoernlund 			    struct net_bridge *br,
618b6d0425bSHenrik Bjoernlund 			    bool getlink)
619e77824d8SHenrik Bjoernlund {
620e77824d8SHenrik Bjoernlund 	struct br_cfm_peer_mep *peer_mep;
621e77824d8SHenrik Bjoernlund 	struct br_cfm_mep *mep;
622e77824d8SHenrik Bjoernlund 	struct nlattr *tb;
623e77824d8SHenrik Bjoernlund 
624e77824d8SHenrik Bjoernlund 	hlist_for_each_entry_rcu(mep, &br->mep_list, head) {
625e77824d8SHenrik Bjoernlund 		tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INFO);
626e77824d8SHenrik Bjoernlund 		if (!tb)
627e77824d8SHenrik Bjoernlund 			goto nla_info_failure;
628e77824d8SHenrik Bjoernlund 
629e77824d8SHenrik Bjoernlund 		if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE,
630e77824d8SHenrik Bjoernlund 				mep->instance))
631e77824d8SHenrik Bjoernlund 			goto nla_put_failure;
632e77824d8SHenrik Bjoernlund 
633e77824d8SHenrik Bjoernlund 		if (nla_put_u32(skb,
634e77824d8SHenrik Bjoernlund 				IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN,
635e77824d8SHenrik Bjoernlund 				mep->status.opcode_unexp_seen))
636e77824d8SHenrik Bjoernlund 			goto nla_put_failure;
637e77824d8SHenrik Bjoernlund 
638e77824d8SHenrik Bjoernlund 		if (nla_put_u32(skb,
639e77824d8SHenrik Bjoernlund 				IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN,
640e77824d8SHenrik Bjoernlund 				mep->status.version_unexp_seen))
641e77824d8SHenrik Bjoernlund 			goto nla_put_failure;
642e77824d8SHenrik Bjoernlund 
643e77824d8SHenrik Bjoernlund 		if (nla_put_u32(skb,
644e77824d8SHenrik Bjoernlund 				IFLA_BRIDGE_CFM_MEP_STATUS_RX_LEVEL_LOW_SEEN,
645e77824d8SHenrik Bjoernlund 				mep->status.rx_level_low_seen))
646e77824d8SHenrik Bjoernlund 			goto nla_put_failure;
647e77824d8SHenrik Bjoernlund 
648b6d0425bSHenrik Bjoernlund 		/* Only clear if this is a GETLINK */
649b6d0425bSHenrik Bjoernlund 		if (getlink) {
650e77824d8SHenrik Bjoernlund 			/* Clear all 'seen' indications */
651e77824d8SHenrik Bjoernlund 			mep->status.opcode_unexp_seen = false;
652e77824d8SHenrik Bjoernlund 			mep->status.version_unexp_seen = false;
653e77824d8SHenrik Bjoernlund 			mep->status.rx_level_low_seen = false;
654b6d0425bSHenrik Bjoernlund 		}
655e77824d8SHenrik Bjoernlund 
656e77824d8SHenrik Bjoernlund 		nla_nest_end(skb, tb);
657e77824d8SHenrik Bjoernlund 
658e77824d8SHenrik Bjoernlund 		hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) {
659e77824d8SHenrik Bjoernlund 			tb = nla_nest_start(skb,
660e77824d8SHenrik Bjoernlund 					    IFLA_BRIDGE_CFM_CC_PEER_STATUS_INFO);
661e77824d8SHenrik Bjoernlund 			if (!tb)
662e77824d8SHenrik Bjoernlund 				goto nla_info_failure;
663e77824d8SHenrik Bjoernlund 
664e77824d8SHenrik Bjoernlund 			if (nla_put_u32(skb,
665e77824d8SHenrik Bjoernlund 					IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE,
666e77824d8SHenrik Bjoernlund 					mep->instance))
667e77824d8SHenrik Bjoernlund 				goto nla_put_failure;
668e77824d8SHenrik Bjoernlund 
669e77824d8SHenrik Bjoernlund 			if (nla_put_u32(skb,
670e77824d8SHenrik Bjoernlund 					IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID,
671e77824d8SHenrik Bjoernlund 					peer_mep->mepid))
672e77824d8SHenrik Bjoernlund 				goto nla_put_failure;
673e77824d8SHenrik Bjoernlund 
674e77824d8SHenrik Bjoernlund 			if (nla_put_u32(skb,
675e77824d8SHenrik Bjoernlund 					IFLA_BRIDGE_CFM_CC_PEER_STATUS_CCM_DEFECT,
676e77824d8SHenrik Bjoernlund 					peer_mep->cc_status.ccm_defect))
677e77824d8SHenrik Bjoernlund 				goto nla_put_failure;
678e77824d8SHenrik Bjoernlund 
679e77824d8SHenrik Bjoernlund 			if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI,
680e77824d8SHenrik Bjoernlund 					peer_mep->cc_status.rdi))
681e77824d8SHenrik Bjoernlund 				goto nla_put_failure;
682e77824d8SHenrik Bjoernlund 
683e77824d8SHenrik Bjoernlund 			if (nla_put_u8(skb,
684e77824d8SHenrik Bjoernlund 				       IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE,
685e77824d8SHenrik Bjoernlund 				       peer_mep->cc_status.port_tlv_value))
686e77824d8SHenrik Bjoernlund 				goto nla_put_failure;
687e77824d8SHenrik Bjoernlund 
688e77824d8SHenrik Bjoernlund 			if (nla_put_u8(skb,
689e77824d8SHenrik Bjoernlund 				       IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE,
690e77824d8SHenrik Bjoernlund 				       peer_mep->cc_status.if_tlv_value))
691e77824d8SHenrik Bjoernlund 				goto nla_put_failure;
692e77824d8SHenrik Bjoernlund 
693e77824d8SHenrik Bjoernlund 			if (nla_put_u32(skb,
694e77824d8SHenrik Bjoernlund 					IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN,
695e77824d8SHenrik Bjoernlund 					peer_mep->cc_status.seen))
696e77824d8SHenrik Bjoernlund 				goto nla_put_failure;
697e77824d8SHenrik Bjoernlund 
698e77824d8SHenrik Bjoernlund 			if (nla_put_u32(skb,
699e77824d8SHenrik Bjoernlund 					IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN,
700e77824d8SHenrik Bjoernlund 					peer_mep->cc_status.tlv_seen))
701e77824d8SHenrik Bjoernlund 				goto nla_put_failure;
702e77824d8SHenrik Bjoernlund 
703e77824d8SHenrik Bjoernlund 			if (nla_put_u32(skb,
704e77824d8SHenrik Bjoernlund 					IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEQ_UNEXP_SEEN,
705e77824d8SHenrik Bjoernlund 					peer_mep->cc_status.seq_unexp_seen))
706e77824d8SHenrik Bjoernlund 				goto nla_put_failure;
707e77824d8SHenrik Bjoernlund 
708b6d0425bSHenrik Bjoernlund 			if (getlink) { /* Only clear if this is a GETLINK */
709e77824d8SHenrik Bjoernlund 				/* Clear all 'seen' indications */
710e77824d8SHenrik Bjoernlund 				peer_mep->cc_status.seen = false;
711e77824d8SHenrik Bjoernlund 				peer_mep->cc_status.tlv_seen = false;
712e77824d8SHenrik Bjoernlund 				peer_mep->cc_status.seq_unexp_seen = false;
713b6d0425bSHenrik Bjoernlund 			}
714e77824d8SHenrik Bjoernlund 
715e77824d8SHenrik Bjoernlund 			nla_nest_end(skb, tb);
716e77824d8SHenrik Bjoernlund 		}
717e77824d8SHenrik Bjoernlund 	}
718e77824d8SHenrik Bjoernlund 
719e77824d8SHenrik Bjoernlund 	return 0;
720e77824d8SHenrik Bjoernlund 
721e77824d8SHenrik Bjoernlund nla_put_failure:
722e77824d8SHenrik Bjoernlund 	nla_nest_cancel(skb, tb);
723e77824d8SHenrik Bjoernlund 
724e77824d8SHenrik Bjoernlund nla_info_failure:
725e77824d8SHenrik Bjoernlund 	return -EMSGSIZE;
726e77824d8SHenrik Bjoernlund }
727