cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

br_cfm_netlink.c (21221B)


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